prjct-cli 1.7.0 → 1.7.2

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.
@@ -932,6 +932,60 @@ var init_author_detector = __esm({
932
932
  }
933
933
  });
934
934
 
935
+ // core/storage/safe-reader.ts
936
+ import fs4 from "node:fs/promises";
937
+ async function safeRead(filePath, schema) {
938
+ let content;
939
+ try {
940
+ content = await fs4.readFile(filePath, "utf-8");
941
+ } catch (error) {
942
+ if (isNotFoundError(error)) {
943
+ return null;
944
+ }
945
+ throw error;
946
+ }
947
+ let raw;
948
+ try {
949
+ raw = JSON.parse(content);
950
+ } catch {
951
+ await createBackup(filePath, content);
952
+ logCorruption(filePath, "Malformed JSON");
953
+ return null;
954
+ }
955
+ const result = schema.safeParse(raw);
956
+ if (result.success) {
957
+ return raw;
958
+ }
959
+ await createBackup(filePath, content);
960
+ logCorruption(filePath, formatZodError(result.error));
961
+ return null;
962
+ }
963
+ async function createBackup(filePath, content) {
964
+ const backupPath = `${filePath}.backup`;
965
+ try {
966
+ await fs4.writeFile(backupPath, content, "utf-8");
967
+ } catch {
968
+ }
969
+ }
970
+ function logCorruption(filePath, reason2) {
971
+ console.error(`[prjct] Warning: Corrupted storage file: ${filePath}`);
972
+ console.error(`[prjct] Reason: ${reason2}`);
973
+ console.error(`[prjct] A .backup file has been created. Returning defaults.`);
974
+ }
975
+ function formatZodError(error) {
976
+ return error.issues.slice(0, 3).map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
977
+ }
978
+ var init_safe_reader = __esm({
979
+ "core/storage/safe-reader.ts"() {
980
+ "use strict";
981
+ init_fs();
982
+ __name(safeRead, "safeRead");
983
+ __name(createBackup, "createBackup");
984
+ __name(logCorruption, "logCorruption");
985
+ __name(formatZodError, "formatZodError");
986
+ }
987
+ });
988
+
935
989
  // core/utils/file-helper.ts
936
990
  var file_helper_exports = {};
937
991
  __export(file_helper_exports, {
@@ -958,11 +1012,15 @@ __export(file_helper_exports, {
958
1012
  writeJson: () => writeJson,
959
1013
  writeLines: () => writeLines
960
1014
  });
961
- import fs4 from "node:fs/promises";
1015
+ import fs5 from "node:fs/promises";
962
1016
  import path4 from "node:path";
963
- async function readJson(filePath, defaultValue = null) {
1017
+ async function readJson(filePath, defaultValue = null, schema) {
1018
+ if (schema) {
1019
+ const data = await safeRead(filePath, schema);
1020
+ return data ?? defaultValue;
1021
+ }
964
1022
  try {
965
- const content = await fs4.readFile(filePath, "utf-8");
1023
+ const content = await fs5.readFile(filePath, "utf-8");
966
1024
  return JSON.parse(content);
967
1025
  } catch (error) {
968
1026
  if (isNotFoundError(error)) {
@@ -973,11 +1031,11 @@ async function readJson(filePath, defaultValue = null) {
973
1031
  }
974
1032
  async function writeJson(filePath, data, indent = 2) {
975
1033
  const content = JSON.stringify(data, null, indent);
976
- await fs4.writeFile(filePath, content, "utf-8");
1034
+ await fs5.writeFile(filePath, content, "utf-8");
977
1035
  }
978
1036
  async function readFile(filePath, defaultValue = "") {
979
1037
  try {
980
- return await fs4.readFile(filePath, "utf-8");
1038
+ return await fs5.readFile(filePath, "utf-8");
981
1039
  } catch (error) {
982
1040
  if (isNotFoundError(error)) {
983
1041
  return defaultValue;
@@ -987,32 +1045,32 @@ async function readFile(filePath, defaultValue = "") {
987
1045
  }
988
1046
  async function writeFile(filePath, content) {
989
1047
  const dir = path4.dirname(filePath);
990
- await fs4.mkdir(dir, { recursive: true });
991
- await fs4.writeFile(filePath, content, "utf-8");
1048
+ await fs5.mkdir(dir, { recursive: true });
1049
+ await fs5.writeFile(filePath, content, "utf-8");
992
1050
  }
993
1051
  async function atomicWrite(filePath, content) {
994
1052
  const dir = path4.dirname(filePath);
995
- await fs4.mkdir(dir, { recursive: true });
1053
+ await fs5.mkdir(dir, { recursive: true });
996
1054
  const tempPath = `${filePath}.${Date.now()}.tmp`;
997
- await fs4.writeFile(tempPath, content, "utf-8");
998
- await fs4.rename(tempPath, filePath);
1055
+ await fs5.writeFile(tempPath, content, "utf-8");
1056
+ await fs5.rename(tempPath, filePath);
999
1057
  }
1000
1058
  async function appendToFile(filePath, content) {
1001
- await fs4.appendFile(filePath, content, "utf-8");
1059
+ await fs5.appendFile(filePath, content, "utf-8");
1002
1060
  }
1003
1061
  async function appendLine(filePath, line) {
1004
1062
  const dir = path4.dirname(filePath);
1005
- await fs4.mkdir(dir, { recursive: true });
1006
- await fs4.appendFile(filePath, `${line}
1063
+ await fs5.mkdir(dir, { recursive: true });
1064
+ await fs5.appendFile(filePath, `${line}
1007
1065
  `, "utf-8");
1008
1066
  }
1009
1067
  async function prependToFile(filePath, content) {
1010
1068
  try {
1011
- const existing = await fs4.readFile(filePath, "utf-8");
1012
- await fs4.writeFile(filePath, content + existing, "utf-8");
1069
+ const existing = await fs5.readFile(filePath, "utf-8");
1070
+ await fs5.writeFile(filePath, content + existing, "utf-8");
1013
1071
  } catch (error) {
1014
1072
  if (isNotFoundError(error)) {
1015
- await fs4.writeFile(filePath, content, "utf-8");
1073
+ await fs5.writeFile(filePath, content, "utf-8");
1016
1074
  } else {
1017
1075
  throw error;
1018
1076
  }
@@ -1020,7 +1078,7 @@ async function prependToFile(filePath, content) {
1020
1078
  }
1021
1079
  async function fileExists2(filePath) {
1022
1080
  try {
1023
- await fs4.access(filePath);
1081
+ await fs5.access(filePath);
1024
1082
  return true;
1025
1083
  } catch (error) {
1026
1084
  if (isNotFoundError(error)) {
@@ -1031,7 +1089,7 @@ async function fileExists2(filePath) {
1031
1089
  }
1032
1090
  async function dirExists(dirPath) {
1033
1091
  try {
1034
- const stats = await fs4.stat(dirPath);
1092
+ const stats = await fs5.stat(dirPath);
1035
1093
  return stats.isDirectory();
1036
1094
  } catch (error) {
1037
1095
  if (isNotFoundError(error)) {
@@ -1041,11 +1099,11 @@ async function dirExists(dirPath) {
1041
1099
  }
1042
1100
  }
1043
1101
  async function ensureDir(dirPath) {
1044
- await fs4.mkdir(dirPath, { recursive: true });
1102
+ await fs5.mkdir(dirPath, { recursive: true });
1045
1103
  }
1046
1104
  async function deleteFile(filePath) {
1047
1105
  try {
1048
- await fs4.unlink(filePath);
1106
+ await fs5.unlink(filePath);
1049
1107
  return true;
1050
1108
  } catch (error) {
1051
1109
  if (isNotFoundError(error)) {
@@ -1056,7 +1114,7 @@ async function deleteFile(filePath) {
1056
1114
  }
1057
1115
  async function deleteDir(dirPath) {
1058
1116
  try {
1059
- await fs4.rm(dirPath, { recursive: true, force: true });
1117
+ await fs5.rm(dirPath, { recursive: true, force: true });
1060
1118
  return true;
1061
1119
  } catch (error) {
1062
1120
  if (isNotFoundError(error)) {
@@ -1067,7 +1125,7 @@ async function deleteDir(dirPath) {
1067
1125
  }
1068
1126
  async function listFiles(dirPath, options = {}) {
1069
1127
  try {
1070
- const entries = await fs4.readdir(dirPath, { withFileTypes: true });
1128
+ const entries = await fs5.readdir(dirPath, { withFileTypes: true });
1071
1129
  let files = entries;
1072
1130
  if (options.filesOnly) {
1073
1131
  files = files.filter((entry) => entry.isFile());
@@ -1087,18 +1145,18 @@ async function listFiles(dirPath, options = {}) {
1087
1145
  }
1088
1146
  }
1089
1147
  async function getFileSize(filePath) {
1090
- const stats = await fs4.stat(filePath);
1148
+ const stats = await fs5.stat(filePath);
1091
1149
  return stats.size;
1092
1150
  }
1093
1151
  async function getFileModifiedTime(filePath) {
1094
- const stats = await fs4.stat(filePath);
1152
+ const stats = await fs5.stat(filePath);
1095
1153
  return stats.mtime;
1096
1154
  }
1097
1155
  async function copyFile(sourcePath, destPath) {
1098
- await fs4.copyFile(sourcePath, destPath);
1156
+ await fs5.copyFile(sourcePath, destPath);
1099
1157
  }
1100
1158
  async function moveFile(oldPath, newPath) {
1101
- await fs4.rename(oldPath, newPath);
1159
+ await fs5.rename(oldPath, newPath);
1102
1160
  }
1103
1161
  async function readLines(filePath) {
1104
1162
  const content = await readFile(filePath, "");
@@ -1117,6 +1175,7 @@ function getFileNameWithoutExtension(filePath) {
1117
1175
  var init_file_helper = __esm({
1118
1176
  "core/utils/file-helper.ts"() {
1119
1177
  "use strict";
1178
+ init_safe_reader();
1120
1179
  init_fs();
1121
1180
  __name(readJson, "readJson");
1122
1181
  __name(writeJson, "writeJson");
@@ -1145,7 +1204,7 @@ var init_file_helper = __esm({
1145
1204
 
1146
1205
  // core/infrastructure/path-manager.ts
1147
1206
  import crypto2 from "node:crypto";
1148
- import fs5 from "node:fs/promises";
1207
+ import fs6 from "node:fs/promises";
1149
1208
  import os3 from "node:os";
1150
1209
  import path5 from "node:path";
1151
1210
  import { globSync } from "glob";
@@ -1285,17 +1344,17 @@ var init_path_manager = __esm({
1285
1344
  const sessionsDir = path5.join(this.getGlobalProjectPath(projectId), "sessions");
1286
1345
  const sessions = [];
1287
1346
  try {
1288
- const years = await fs5.readdir(sessionsDir, { withFileTypes: true });
1347
+ const years = await fs6.readdir(sessionsDir, { withFileTypes: true });
1289
1348
  for (const yearEntry of years) {
1290
1349
  if (!yearEntry.isDirectory()) continue;
1291
1350
  if (year && yearEntry.name !== year.toString()) continue;
1292
1351
  const yearPath = path5.join(sessionsDir, yearEntry.name);
1293
- const months = await fs5.readdir(yearPath, { withFileTypes: true });
1352
+ const months = await fs6.readdir(yearPath, { withFileTypes: true });
1294
1353
  for (const monthEntry of months) {
1295
1354
  if (!monthEntry.isDirectory()) continue;
1296
1355
  if (month && monthEntry.name !== month.toString().padStart(2, "0")) continue;
1297
1356
  const monthPath = path5.join(yearPath, monthEntry.name);
1298
- const days = await fs5.readdir(monthPath, { withFileTypes: true });
1357
+ const days = await fs6.readdir(monthPath, { withFileTypes: true });
1299
1358
  for (const dayEntry of days) {
1300
1359
  if (!dayEntry.isDirectory()) continue;
1301
1360
  sessions.push({
@@ -1333,7 +1392,7 @@ var init_path_manager = __esm({
1333
1392
  async listProjects() {
1334
1393
  try {
1335
1394
  await this.ensureGlobalStructure();
1336
- const entries = await fs5.readdir(this.globalProjectsDir, { withFileTypes: true });
1395
+ const entries = await fs6.readdir(this.globalProjectsDir, { withFileTypes: true });
1337
1396
  return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
1338
1397
  } catch (_error) {
1339
1398
  return [];
@@ -1473,7 +1532,7 @@ var init_path_manager = __esm({
1473
1532
  const packageJsonPath = path5.join(projectPath, "package.json");
1474
1533
  if (await fileExists2(packageJsonPath)) {
1475
1534
  try {
1476
- const content = await fs5.readFile(packageJsonPath, "utf-8");
1535
+ const content = await fs6.readFile(packageJsonPath, "utf-8");
1477
1536
  const pkg = JSON.parse(content);
1478
1537
  if (pkg.workspaces) {
1479
1538
  result.isMonorepo = true;
@@ -1496,14 +1555,14 @@ var init_path_manager = __esm({
1496
1555
  let patterns = [];
1497
1556
  try {
1498
1557
  if (type === "pnpm") {
1499
- const yaml = await fs5.readFile(path5.join(rootPath, "pnpm-workspace.yaml"), "utf-8");
1558
+ const yaml = await fs6.readFile(path5.join(rootPath, "pnpm-workspace.yaml"), "utf-8");
1500
1559
  const match = yaml.match(/packages:\s*\n((?:\s*-\s*.+\n?)+)/);
1501
1560
  if (match) {
1502
1561
  patterns = match[1].split("\n").map((line) => line.replace(/^\s*-\s*['"]?|['"]?\s*$/g, "")).filter(Boolean);
1503
1562
  }
1504
1563
  } else if (type === "npm" || type === "lerna") {
1505
1564
  const packageJsonPath = path5.join(rootPath, "package.json");
1506
- const content = await fs5.readFile(packageJsonPath, "utf-8");
1565
+ const content = await fs6.readFile(packageJsonPath, "utf-8");
1507
1566
  const pkg = JSON.parse(content);
1508
1567
  if (Array.isArray(pkg.workspaces)) {
1509
1568
  patterns = pkg.workspaces;
@@ -1513,7 +1572,7 @@ var init_path_manager = __esm({
1513
1572
  if (type === "lerna") {
1514
1573
  const lernaPath = path5.join(rootPath, "lerna.json");
1515
1574
  if (await fileExists2(lernaPath)) {
1516
- const lernaContent = await fs5.readFile(lernaPath, "utf-8");
1575
+ const lernaContent = await fs6.readFile(lernaPath, "utf-8");
1517
1576
  const lerna = JSON.parse(lernaContent);
1518
1577
  if (lerna.packages) {
1519
1578
  patterns = lerna.packages;
@@ -1524,7 +1583,7 @@ var init_path_manager = __esm({
1524
1583
  patterns = ["apps/*", "libs/*", "packages/*"];
1525
1584
  } else if (type === "turborepo") {
1526
1585
  const packageJsonPath = path5.join(rootPath, "package.json");
1527
- const content = await fs5.readFile(packageJsonPath, "utf-8");
1586
+ const content = await fs6.readFile(packageJsonPath, "utf-8");
1528
1587
  const pkg = JSON.parse(content);
1529
1588
  if (Array.isArray(pkg.workspaces)) {
1530
1589
  patterns = pkg.workspaces;
@@ -1544,7 +1603,7 @@ var init_path_manager = __esm({
1544
1603
  const packageJsonPath = path5.join(packagePath, "package.json");
1545
1604
  if (await fileExists2(packageJsonPath)) {
1546
1605
  try {
1547
- const content = await fs5.readFile(packageJsonPath, "utf-8");
1606
+ const content = await fs6.readFile(packageJsonPath, "utf-8");
1548
1607
  const pkg = JSON.parse(content);
1549
1608
  const prjctMdPath = path5.join(packagePath, "PRJCT.md");
1550
1609
  packages.push({
@@ -1600,7 +1659,7 @@ var init_path_manager = __esm({
1600
1659
  });
1601
1660
 
1602
1661
  // core/infrastructure/config-manager.ts
1603
- import fs6 from "node:fs/promises";
1662
+ import fs7 from "node:fs/promises";
1604
1663
  import path6 from "node:path";
1605
1664
  import * as jsonc from "jsonc-parser";
1606
1665
  function parseJsonc(content) {
@@ -1639,7 +1698,7 @@ var init_config_manager = __esm({
1639
1698
  async readConfig(projectPath) {
1640
1699
  try {
1641
1700
  const configPath = path_manager_default.getLocalConfigPath(projectPath);
1642
- const content = await fs6.readFile(configPath, "utf-8");
1701
+ const content = await fs7.readFile(configPath, "utf-8");
1643
1702
  return parseJsonc(content);
1644
1703
  } catch (error) {
1645
1704
  if (isNotFoundError(error)) {
@@ -1655,9 +1714,9 @@ var init_config_manager = __esm({
1655
1714
  async writeConfig(projectPath, config) {
1656
1715
  const configPath = path_manager_default.getLocalConfigPath(projectPath);
1657
1716
  const configDir = path_manager_default.getLegacyPrjctPath(projectPath);
1658
- await fs6.mkdir(configDir, { recursive: true });
1717
+ await fs7.mkdir(configDir, { recursive: true });
1659
1718
  const content = JSON.stringify(config, null, 2);
1660
- await fs6.writeFile(configPath, `${content}
1719
+ await fs7.writeFile(configPath, `${content}
1661
1720
  `, "utf-8");
1662
1721
  }
1663
1722
  /**
@@ -1668,7 +1727,7 @@ var init_config_manager = __esm({
1668
1727
  async readGlobalConfig(projectId) {
1669
1728
  try {
1670
1729
  const configPath = path_manager_default.getGlobalProjectConfigPath(projectId);
1671
- const content = await fs6.readFile(configPath, "utf-8");
1730
+ const content = await fs7.readFile(configPath, "utf-8");
1672
1731
  return parseJsonc(content);
1673
1732
  } catch (error) {
1674
1733
  if (isNotFoundError(error)) {
@@ -1686,9 +1745,9 @@ var init_config_manager = __esm({
1686
1745
  async writeGlobalConfig(projectId, config) {
1687
1746
  const configPath = path_manager_default.getGlobalProjectConfigPath(projectId);
1688
1747
  const configDir = path_manager_default.getGlobalProjectPath(projectId);
1689
- await fs6.mkdir(configDir, { recursive: true });
1748
+ await fs7.mkdir(configDir, { recursive: true });
1690
1749
  const content = JSON.stringify(config, null, 2);
1691
- await fs6.writeFile(configPath, `${content}
1750
+ await fs7.writeFile(configPath, `${content}
1692
1751
  `, "utf-8");
1693
1752
  }
1694
1753
  /**
@@ -1778,7 +1837,7 @@ var init_config_manager = __esm({
1778
1837
  if (!config || !config.projectId) return true;
1779
1838
  const globalPath = path_manager_default.getGlobalProjectPath(config.projectId);
1780
1839
  try {
1781
- const coreFiles = await fs6.readdir(path6.join(globalPath, "core"));
1840
+ const coreFiles = await fs7.readdir(path6.join(globalPath, "core"));
1782
1841
  return coreFiles.length === 0;
1783
1842
  } catch (error) {
1784
1843
  if (isNotFoundError(error)) {
@@ -1901,7 +1960,7 @@ var init_config_manager = __esm({
1901
1960
  });
1902
1961
 
1903
1962
  // core/infrastructure/editors-config.ts
1904
- import fs7 from "node:fs/promises";
1963
+ import fs8 from "node:fs/promises";
1905
1964
  import os4 from "node:os";
1906
1965
  import path7 from "node:path";
1907
1966
  var EditorsConfig, editorsConfig, editors_config_default;
@@ -1926,7 +1985,7 @@ var init_editors_config = __esm({
1926
1985
  */
1927
1986
  async ensureConfigDir() {
1928
1987
  try {
1929
- await fs7.mkdir(this.configDir, { recursive: true });
1988
+ await fs8.mkdir(this.configDir, { recursive: true });
1930
1989
  } catch (error) {
1931
1990
  console.error("[editors-config] Error creating config directory:", getErrorMessage2(error));
1932
1991
  }
@@ -1936,7 +1995,7 @@ var init_editors_config = __esm({
1936
1995
  */
1937
1996
  async loadConfig() {
1938
1997
  try {
1939
- const content = await fs7.readFile(this.configFile, "utf-8");
1998
+ const content = await fs8.readFile(this.configFile, "utf-8");
1940
1999
  return JSON.parse(content);
1941
2000
  } catch (error) {
1942
2001
  if (error.code === "ENOENT") {
@@ -1960,7 +2019,7 @@ var init_editors_config = __esm({
1960
2019
  lastInstall: (/* @__PURE__ */ new Date()).toISOString(),
1961
2020
  path: installPath
1962
2021
  };
1963
- await fs7.writeFile(this.configFile, JSON.stringify(config, null, 2), "utf-8");
2022
+ await fs8.writeFile(this.configFile, JSON.stringify(config, null, 2), "utf-8");
1964
2023
  return true;
1965
2024
  } catch (error) {
1966
2025
  console.error("[editors-config] Error saving config:", getErrorMessage2(error));
@@ -2000,7 +2059,7 @@ var init_editors_config = __esm({
2000
2059
  }
2001
2060
  config.version = version;
2002
2061
  config.lastInstall = (/* @__PURE__ */ new Date()).toISOString();
2003
- await fs7.writeFile(this.configFile, JSON.stringify(config, null, 2), "utf-8");
2062
+ await fs8.writeFile(this.configFile, JSON.stringify(config, null, 2), "utf-8");
2004
2063
  return true;
2005
2064
  } catch (error) {
2006
2065
  console.error("[editors-config] Error updating version:", getErrorMessage2(error));
@@ -2012,7 +2071,7 @@ var init_editors_config = __esm({
2012
2071
  */
2013
2072
  async configExists() {
2014
2073
  try {
2015
- await fs7.access(this.configFile);
2074
+ await fs8.access(this.configFile);
2016
2075
  return true;
2017
2076
  } catch (_error) {
2018
2077
  return false;
@@ -2026,7 +2085,7 @@ var init_editors_config = __esm({
2026
2085
  try {
2027
2086
  const exists = await this.configExists();
2028
2087
  if (exists) {
2029
- await fs7.unlink(this.configFile);
2088
+ await fs8.unlink(this.configFile);
2030
2089
  }
2031
2090
  return true;
2032
2091
  } catch (error) {
@@ -2709,7 +2768,7 @@ __export(session_tracker_exports, {
2709
2768
  default: () => session_tracker_default,
2710
2769
  sessionTracker: () => sessionTracker
2711
2770
  });
2712
- import fs10 from "node:fs/promises";
2771
+ import fs11 from "node:fs/promises";
2713
2772
  import path10 from "node:path";
2714
2773
  var SESSION_FILENAME, DEFAULT_IDLE_TIMEOUT_MS, MAX_COMMAND_HISTORY, MAX_FILE_HISTORY, SessionTracker, sessionTracker, session_tracker_default;
2715
2774
  var init_session_tracker = __esm({
@@ -2735,7 +2794,7 @@ var init_session_tracker = __esm({
2735
2794
  async read(projectId) {
2736
2795
  const filePath = this.getPath(projectId);
2737
2796
  try {
2738
- const content = await fs10.readFile(filePath, "utf-8");
2797
+ const content = await fs11.readFile(filePath, "utf-8");
2739
2798
  return JSON.parse(content);
2740
2799
  } catch (error) {
2741
2800
  if (isNotFoundError(error) || error instanceof SyntaxError) {
@@ -2749,8 +2808,8 @@ var init_session_tracker = __esm({
2749
2808
  */
2750
2809
  async write(projectId, data) {
2751
2810
  const filePath = this.getPath(projectId);
2752
- await fs10.mkdir(path10.dirname(filePath), { recursive: true });
2753
- await fs10.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
2811
+ await fs11.mkdir(path10.dirname(filePath), { recursive: true });
2812
+ await fs11.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
2754
2813
  }
2755
2814
  getDefault() {
2756
2815
  return {
@@ -2912,7 +2971,7 @@ var start_exports = {};
2912
2971
  __export(start_exports, {
2913
2972
  runStart: () => runStart
2914
2973
  });
2915
- import fs11 from "node:fs/promises";
2974
+ import fs12 from "node:fs/promises";
2916
2975
  import os5 from "node:os";
2917
2976
  import path11 from "node:path";
2918
2977
  import chalk3 from "chalk";
@@ -3018,14 +3077,14 @@ async function installRouter(provider) {
3018
3077
  }
3019
3078
  try {
3020
3079
  const commandsDir = path11.join(config.configDir, "commands");
3021
- await fs11.mkdir(commandsDir, { recursive: true });
3080
+ await fs12.mkdir(commandsDir, { recursive: true });
3022
3081
  const { getPackageRoot: getPackageRoot2 } = await Promise.resolve().then(() => (init_version(), version_exports));
3023
3082
  const packageRoot = getPackageRoot2();
3024
3083
  const routerFile = provider === "claude" ? "p.md" : "p.toml";
3025
3084
  const src = path11.join(packageRoot, "templates", "commands", routerFile);
3026
3085
  const dest = path11.join(commandsDir, routerFile);
3027
3086
  if (await fileExists(src)) {
3028
- await fs11.copyFile(src, dest);
3087
+ await fs12.copyFile(src, dest);
3029
3088
  return true;
3030
3089
  }
3031
3090
  return false;
@@ -3042,16 +3101,16 @@ async function installGlobalConfig(provider) {
3042
3101
  return false;
3043
3102
  }
3044
3103
  try {
3045
- await fs11.mkdir(config.configDir, { recursive: true });
3104
+ await fs12.mkdir(config.configDir, { recursive: true });
3046
3105
  const { getPackageRoot: getPackageRoot2 } = await Promise.resolve().then(() => (init_version(), version_exports));
3047
3106
  const packageRoot = getPackageRoot2();
3048
3107
  const configFile = provider === "claude" ? "CLAUDE.md" : "GEMINI.md";
3049
3108
  const src = path11.join(packageRoot, "templates", "global", configFile);
3050
3109
  const dest = path11.join(config.configDir, configFile);
3051
3110
  if (await fileExists(src)) {
3052
- const content = await fs11.readFile(src, "utf-8");
3111
+ const content = await fs12.readFile(src, "utf-8");
3053
3112
  if (await fileExists(dest)) {
3054
- const existing = await fs11.readFile(dest, "utf-8");
3113
+ const existing = await fs12.readFile(dest, "utf-8");
3055
3114
  const startMarker = "<!-- prjct:start - DO NOT REMOVE THIS MARKER -->";
3056
3115
  const endMarker = "<!-- prjct:end - DO NOT REMOVE THIS MARKER -->";
3057
3116
  if (existing.includes(startMarker) && existing.includes(endMarker)) {
@@ -3061,14 +3120,14 @@ async function installGlobalConfig(provider) {
3061
3120
  content.indexOf(startMarker),
3062
3121
  content.indexOf(endMarker) + endMarker.length
3063
3122
  );
3064
- await fs11.writeFile(dest, before + prjctSection + after);
3123
+ await fs12.writeFile(dest, before + prjctSection + after);
3065
3124
  } else {
3066
- await fs11.writeFile(dest, `${existing}
3125
+ await fs12.writeFile(dest, `${existing}
3067
3126
 
3068
3127
  ${content}`);
3069
3128
  }
3070
3129
  } else {
3071
- await fs11.writeFile(dest, content);
3130
+ await fs12.writeFile(dest, content);
3072
3131
  }
3073
3132
  return true;
3074
3133
  }
@@ -3082,7 +3141,7 @@ ${content}`);
3082
3141
  }
3083
3142
  async function saveSetupConfig(providers) {
3084
3143
  const configDir = path11.join(os5.homedir(), ".prjct-cli", "config");
3085
- await fs11.mkdir(configDir, { recursive: true });
3144
+ await fs12.mkdir(configDir, { recursive: true });
3086
3145
  const configPath = path11.join(configDir, "installed-editors.json");
3087
3146
  const config = {
3088
3147
  version: VERSION,
@@ -3093,7 +3152,7 @@ async function saveSetupConfig(providers) {
3093
3152
  lastInstall: (/* @__PURE__ */ new Date()).toISOString(),
3094
3153
  path: path11.join(os5.homedir(), `.${providers[0]}`, "commands")
3095
3154
  };
3096
- await fs11.writeFile(configPath, JSON.stringify(config, null, 2));
3155
+ await fs12.writeFile(configPath, JSON.stringify(config, null, 2));
3097
3156
  }
3098
3157
  function showCompletion(providers) {
3099
3158
  console.log(`
@@ -3123,7 +3182,7 @@ async function runStart() {
3123
3182
  showBanner();
3124
3183
  const configPath = path11.join(os5.homedir(), ".prjct-cli", "config", "installed-editors.json");
3125
3184
  if (await fileExists(configPath)) {
3126
- const existing = JSON.parse(await fs11.readFile(configPath, "utf-8"));
3185
+ const existing = JSON.parse(await fs12.readFile(configPath, "utf-8"));
3127
3186
  if (existing.version === VERSION) {
3128
3187
  console.log(` ${chalk3.yellow("\u2139")} Already configured for v${VERSION}`);
3129
3188
  console.log(` ${chalk3.dim("Run with --force to reconfigure")}
@@ -3477,7 +3536,7 @@ var init_cache = __esm({
3477
3536
  });
3478
3537
 
3479
3538
  // core/storage/storage-manager.ts
3480
- import fs12 from "node:fs/promises";
3539
+ import fs13 from "node:fs/promises";
3481
3540
  import path12 from "node:path";
3482
3541
  var StorageManager;
3483
3542
  var init_storage_manager = __esm({
@@ -3488,15 +3547,18 @@ var init_storage_manager = __esm({
3488
3547
  init_fs();
3489
3548
  init_cache();
3490
3549
  init_date_helper();
3550
+ init_safe_reader();
3491
3551
  StorageManager = class {
3492
3552
  static {
3493
3553
  __name(this, "StorageManager");
3494
3554
  }
3495
3555
  filename;
3496
3556
  cache;
3497
- constructor(filename) {
3557
+ schema;
3558
+ constructor(filename, schema) {
3498
3559
  this.filename = filename;
3499
3560
  this.cache = new TTLCache({ ttl: 5e3, maxSize: 50 });
3561
+ this.schema = schema ?? null;
3500
3562
  }
3501
3563
  /**
3502
3564
  * Get file path for storage JSON
@@ -3513,7 +3575,9 @@ var init_storage_manager = __esm({
3513
3575
  return path_manager_default.getFilePath(projectId, layer, mdFilename);
3514
3576
  }
3515
3577
  /**
3516
- * Read data from storage
3578
+ * Read data from storage with optional Zod validation.
3579
+ * When a schema is provided (via constructor), validates after JSON.parse.
3580
+ * On corruption: creates .backup file, logs warning, returns default.
3517
3581
  */
3518
3582
  async read(projectId) {
3519
3583
  const cached = this.cache.get(projectId);
@@ -3521,8 +3585,16 @@ var init_storage_manager = __esm({
3521
3585
  return cached;
3522
3586
  }
3523
3587
  const filePath = this.getStoragePath(projectId);
3588
+ if (this.schema) {
3589
+ const data = await safeRead(filePath, this.schema);
3590
+ if (data !== null) {
3591
+ this.cache.set(projectId, data);
3592
+ return data;
3593
+ }
3594
+ return this.getDefault();
3595
+ }
3524
3596
  try {
3525
- const content = await fs12.readFile(filePath, "utf-8");
3597
+ const content = await fs13.readFile(filePath, "utf-8");
3526
3598
  const data = JSON.parse(content);
3527
3599
  this.cache.set(projectId, data);
3528
3600
  return data;
@@ -3539,13 +3611,13 @@ var init_storage_manager = __esm({
3539
3611
  async write(projectId, data) {
3540
3612
  const storagePath = this.getStoragePath(projectId);
3541
3613
  const contextPath = this.getContextPath(projectId, this.getMdFilename());
3542
- await fs12.mkdir(path12.dirname(storagePath), { recursive: true });
3543
- await fs12.mkdir(path12.dirname(contextPath), { recursive: true });
3614
+ await fs13.mkdir(path12.dirname(storagePath), { recursive: true });
3615
+ await fs13.mkdir(path12.dirname(contextPath), { recursive: true });
3544
3616
  const tempPath = `${storagePath}.${Date.now()}.tmp`;
3545
- await fs12.writeFile(tempPath, JSON.stringify(data, null, 2), "utf-8");
3546
- await fs12.rename(tempPath, storagePath);
3617
+ await fs13.writeFile(tempPath, JSON.stringify(data, null, 2), "utf-8");
3618
+ await fs13.rename(tempPath, storagePath);
3547
3619
  const md2 = this.toMarkdown(data);
3548
- await fs12.writeFile(contextPath, md2, "utf-8");
3620
+ await fs13.writeFile(contextPath, md2, "utf-8");
3549
3621
  this.cache.set(projectId, data);
3550
3622
  }
3551
3623
  /**
@@ -3593,7 +3665,7 @@ var init_storage_manager = __esm({
3593
3665
  async exists(projectId) {
3594
3666
  const filePath = this.getStoragePath(projectId);
3595
3667
  try {
3596
- await fs12.access(filePath);
3668
+ await fs13.access(filePath);
3597
3669
  return true;
3598
3670
  } catch (error) {
3599
3671
  if (isNotFoundError(error)) {
@@ -3635,7 +3707,7 @@ var init_metrics_storage = __esm({
3635
3707
  __name(this, "MetricsStorage");
3636
3708
  }
3637
3709
  constructor() {
3638
- super("metrics.json");
3710
+ super("metrics.json", MetricsJsonSchema);
3639
3711
  }
3640
3712
  getDefault() {
3641
3713
  return { ...DEFAULT_METRICS };
@@ -3855,7 +3927,7 @@ var init_metrics_storage = __esm({
3855
3927
 
3856
3928
  // core/context-tools/files-tool.ts
3857
3929
  import { exec as execCallback2 } from "node:child_process";
3858
- import fs13 from "node:fs/promises";
3930
+ import fs14 from "node:fs/promises";
3859
3931
  import path13 from "node:path";
3860
3932
  import { promisify as promisify3 } from "node:util";
3861
3933
  async function findRelevantFiles(taskDescription, projectPath, options = {}) {
@@ -3985,7 +4057,7 @@ async function getAllCodeFiles(projectPath) {
3985
4057
  const files = [];
3986
4058
  async function walk(dir, relativePath = "") {
3987
4059
  try {
3988
- const entries = await fs13.readdir(dir, { withFileTypes: true });
4060
+ const entries = await fs14.readdir(dir, { withFileTypes: true });
3989
4061
  for (const entry of entries) {
3990
4062
  const fullPath = path13.join(dir, entry.name);
3991
4063
  const relPath = path13.join(relativePath, entry.name);
@@ -4289,14 +4361,14 @@ var init_files_tool = __esm({
4289
4361
 
4290
4362
  // core/context-tools/imports-tool.ts
4291
4363
  import { exec as execCallback3 } from "node:child_process";
4292
- import fs14 from "node:fs/promises";
4364
+ import fs15 from "node:fs/promises";
4293
4365
  import path14 from "node:path";
4294
4366
  import { promisify as promisify4 } from "node:util";
4295
4367
  async function analyzeImports(filePath, projectPath = process.cwd(), options = {}) {
4296
4368
  const absolutePath = path14.isAbsolute(filePath) ? filePath : path14.join(projectPath, filePath);
4297
4369
  let content;
4298
4370
  try {
4299
- content = await fs14.readFile(absolutePath, "utf-8");
4371
+ content = await fs15.readFile(absolutePath, "utf-8");
4300
4372
  } catch (error) {
4301
4373
  if (isNotFoundError(error)) {
4302
4374
  return {
@@ -4388,7 +4460,7 @@ async function tryResolve(basePath, projectPath) {
4388
4460
  for (const ext of extensions) {
4389
4461
  const fullPath = basePath + ext;
4390
4462
  try {
4391
- const stat = await fs14.stat(fullPath);
4463
+ const stat = await fs15.stat(fullPath);
4392
4464
  if (stat.isFile()) {
4393
4465
  return path14.relative(projectPath, fullPath);
4394
4466
  }
@@ -4917,13 +4989,13 @@ var init_token_counter = __esm({
4917
4989
  });
4918
4990
 
4919
4991
  // core/context-tools/signatures-tool.ts
4920
- import fs15 from "node:fs/promises";
4992
+ import fs16 from "node:fs/promises";
4921
4993
  import path15 from "node:path";
4922
4994
  async function extractSignatures(filePath, projectPath = process.cwd()) {
4923
4995
  const absolutePath = path15.isAbsolute(filePath) ? filePath : path15.join(projectPath, filePath);
4924
4996
  let content;
4925
4997
  try {
4926
- content = await fs15.readFile(absolutePath, "utf-8");
4998
+ content = await fs16.readFile(absolutePath, "utf-8");
4927
4999
  } catch (error) {
4928
5000
  if (isNotFoundError(error)) {
4929
5001
  return {
@@ -4967,7 +5039,7 @@ async function extractDirectorySignatures(dirPath, projectPath = process.cwd(),
4967
5039
  const absolutePath = path15.isAbsolute(dirPath) ? dirPath : path15.join(projectPath, dirPath);
4968
5040
  const results = [];
4969
5041
  async function processDir(dir) {
4970
- const entries = await fs15.readdir(dir, { withFileTypes: true });
5042
+ const entries = await fs16.readdir(dir, { withFileTypes: true });
4971
5043
  for (const entry of entries) {
4972
5044
  const fullPath = path15.join(dir, entry.name);
4973
5045
  const relativePath = path15.relative(projectPath, fullPath);
@@ -5269,13 +5341,13 @@ var init_signatures_tool = __esm({
5269
5341
  });
5270
5342
 
5271
5343
  // core/context-tools/summary-tool.ts
5272
- import fs16 from "node:fs/promises";
5344
+ import fs17 from "node:fs/promises";
5273
5345
  import path16 from "node:path";
5274
5346
  async function summarizeFile(filePath, projectPath = process.cwd()) {
5275
5347
  const absolutePath = path16.isAbsolute(filePath) ? filePath : path16.join(projectPath, filePath);
5276
5348
  let content;
5277
5349
  try {
5278
- content = await fs16.readFile(absolutePath, "utf-8");
5350
+ content = await fs17.readFile(absolutePath, "utf-8");
5279
5351
  } catch (error) {
5280
5352
  if (isNotFoundError(error)) {
5281
5353
  return {
@@ -5313,7 +5385,7 @@ async function summarizeDirectory(dirPath, projectPath = process.cwd(), options
5313
5385
  const absolutePath = path16.isAbsolute(dirPath) ? dirPath : path16.join(projectPath, dirPath);
5314
5386
  const results = [];
5315
5387
  async function processDir(dir) {
5316
- const entries = await fs16.readdir(dir, { withFileTypes: true });
5388
+ const entries = await fs17.readdir(dir, { withFileTypes: true });
5317
5389
  for (const entry of entries) {
5318
5390
  const fullPath = path16.join(dir, entry.name);
5319
5391
  const relativePath = path16.relative(projectPath, fullPath);
@@ -5575,11 +5647,11 @@ async function runSignaturesTool(args2, projectPath) {
5575
5647
  }
5576
5648
  };
5577
5649
  }
5578
- const fs52 = await import("node:fs/promises");
5650
+ const fs53 = await import("node:fs/promises");
5579
5651
  const path65 = await import("node:path");
5580
5652
  const fullPath = path65.isAbsolute(filePath) ? filePath : path65.join(projectPath, filePath);
5581
5653
  try {
5582
- const stat = await fs52.stat(fullPath);
5654
+ const stat = await fs53.stat(fullPath);
5583
5655
  if (stat.isDirectory()) {
5584
5656
  const results = await extractDirectorySignatures(filePath, projectPath, {
5585
5657
  recursive: args2.includes("--recursive") || args2.includes("-r")
@@ -5646,11 +5718,11 @@ async function runSummaryTool(args2, projectPath) {
5646
5718
  }
5647
5719
  };
5648
5720
  }
5649
- const fs52 = await import("node:fs/promises");
5721
+ const fs53 = await import("node:fs/promises");
5650
5722
  const path65 = await import("node:path");
5651
5723
  const fullPath = path65.isAbsolute(targetPath) ? targetPath : path65.join(projectPath, targetPath);
5652
5724
  try {
5653
- const stat = await fs52.stat(fullPath);
5725
+ const stat = await fs53.stat(fullPath);
5654
5726
  if (stat.isDirectory()) {
5655
5727
  const results = await summarizeDirectory(targetPath, projectPath, {
5656
5728
  recursive: args2.includes("--recursive") || args2.includes("-r")
@@ -5810,7 +5882,7 @@ var hooks_service_exports = {};
5810
5882
  __export(hooks_service_exports, {
5811
5883
  hooksService: () => hooksService
5812
5884
  });
5813
- import fs17 from "node:fs/promises";
5885
+ import fs18 from "node:fs/promises";
5814
5886
  import path17 from "node:path";
5815
5887
  import chalk4 from "chalk";
5816
5888
  function getPostCommitScript() {
@@ -5893,7 +5965,7 @@ function selectStrategy(detected) {
5893
5965
  async function installLefthook(projectPath, hooks) {
5894
5966
  const configFile = await fileExists(path17.join(projectPath, "lefthook.yml")) ? "lefthook.yml" : "lefthook.yaml";
5895
5967
  const configPath = path17.join(projectPath, configFile);
5896
- let content = await fs17.readFile(configPath, "utf-8");
5968
+ let content = await fs18.readFile(configPath, "utf-8");
5897
5969
  for (const hook of hooks) {
5898
5970
  const sectionName = hook;
5899
5971
  const commandName = `prjct-sync-${hook}`;
@@ -5922,7 +5994,7 @@ ${sectionName}:
5922
5994
  ${hookBlock}`;
5923
5995
  }
5924
5996
  }
5925
- await fs17.writeFile(configPath, content, "utf-8");
5997
+ await fs18.writeFile(configPath, content, "utf-8");
5926
5998
  return true;
5927
5999
  }
5928
6000
  async function installHusky(projectPath, hooks) {
@@ -5931,13 +6003,13 @@ async function installHusky(projectPath, hooks) {
5931
6003
  const hookPath = path17.join(huskyDir, hook);
5932
6004
  const script = hook === "post-commit" ? getPostCommitScript() : getPostCheckoutScript();
5933
6005
  if (await fileExists(hookPath)) {
5934
- const existing = await fs17.readFile(hookPath, "utf-8");
6006
+ const existing = await fs18.readFile(hookPath, "utf-8");
5935
6007
  if (existing.includes("prjct sync")) {
5936
6008
  continue;
5937
6009
  }
5938
- await fs17.appendFile(hookPath, "\n# prjct auto-sync\nprjct sync --quiet --yes &\n");
6010
+ await fs18.appendFile(hookPath, "\n# prjct auto-sync\nprjct sync --quiet --yes &\n");
5939
6011
  } else {
5940
- await fs17.writeFile(hookPath, script, { mode: 493 });
6012
+ await fs18.writeFile(hookPath, script, { mode: 493 });
5941
6013
  }
5942
6014
  }
5943
6015
  return true;
@@ -5945,24 +6017,24 @@ async function installHusky(projectPath, hooks) {
5945
6017
  async function installDirect(projectPath, hooks) {
5946
6018
  const hooksDir = path17.join(projectPath, ".git", "hooks");
5947
6019
  if (!await fileExists(hooksDir)) {
5948
- await fs17.mkdir(hooksDir, { recursive: true });
6020
+ await fs18.mkdir(hooksDir, { recursive: true });
5949
6021
  }
5950
6022
  for (const hook of hooks) {
5951
6023
  const hookPath = path17.join(hooksDir, hook);
5952
6024
  const script = hook === "post-commit" ? getPostCommitScript() : getPostCheckoutScript();
5953
6025
  if (await fileExists(hookPath)) {
5954
- const existing = await fs17.readFile(hookPath, "utf-8");
6026
+ const existing = await fs18.readFile(hookPath, "utf-8");
5955
6027
  if (existing.includes("prjct sync")) {
5956
6028
  continue;
5957
6029
  }
5958
- await fs17.appendFile(
6030
+ await fs18.appendFile(
5959
6031
  hookPath,
5960
6032
  `
5961
6033
  # prjct auto-sync
5962
6034
  ${script.split("\n").slice(1).join("\n")}`
5963
6035
  );
5964
6036
  } else {
5965
- await fs17.writeFile(hookPath, script, { mode: 493 });
6037
+ await fs18.writeFile(hookPath, script, { mode: 493 });
5966
6038
  }
5967
6039
  }
5968
6040
  return true;
@@ -5971,10 +6043,10 @@ async function uninstallLefthook(projectPath) {
5971
6043
  const configFile = await fileExists(path17.join(projectPath, "lefthook.yml")) ? "lefthook.yml" : "lefthook.yaml";
5972
6044
  const configPath = path17.join(projectPath, configFile);
5973
6045
  if (!await fileExists(configPath)) return false;
5974
- let content = await fs17.readFile(configPath, "utf-8");
6046
+ let content = await fs18.readFile(configPath, "utf-8");
5975
6047
  content = content.replace(/\s*prjct-sync-[\w-]+:[\s\S]*?(?=\n\S|\n*$)/g, "");
5976
6048
  content = content.replace(/^(post-commit|post-checkout):\s*commands:\s*$/gm, "");
5977
- await fs17.writeFile(configPath, `${content.trimEnd()}
6049
+ await fs18.writeFile(configPath, `${content.trimEnd()}
5978
6050
  `, "utf-8");
5979
6051
  return true;
5980
6052
  }
@@ -5983,13 +6055,13 @@ async function uninstallHusky(projectPath) {
5983
6055
  for (const hook of ["post-commit", "post-checkout"]) {
5984
6056
  const hookPath = path17.join(huskyDir, hook);
5985
6057
  if (!await fileExists(hookPath)) continue;
5986
- const content = await fs17.readFile(hookPath, "utf-8");
6058
+ const content = await fs18.readFile(hookPath, "utf-8");
5987
6059
  if (!content.includes("prjct sync")) continue;
5988
6060
  const cleaned = content.split("\n").filter((line) => !line.includes("prjct sync") && !line.includes("prjct auto-sync")).join("\n");
5989
6061
  if (cleaned.trim() === "#!/bin/sh" || cleaned.trim() === "#!/usr/bin/env sh") {
5990
- await fs17.unlink(hookPath);
6062
+ await fs18.unlink(hookPath);
5991
6063
  } else {
5992
- await fs17.writeFile(hookPath, cleaned, { mode: 493 });
6064
+ await fs18.writeFile(hookPath, cleaned, { mode: 493 });
5993
6065
  }
5994
6066
  }
5995
6067
  return true;
@@ -5999,13 +6071,13 @@ async function uninstallDirect(projectPath) {
5999
6071
  for (const hook of ["post-commit", "post-checkout"]) {
6000
6072
  const hookPath = path17.join(hooksDir, hook);
6001
6073
  if (!await fileExists(hookPath)) continue;
6002
- const content = await fs17.readFile(hookPath, "utf-8");
6074
+ const content = await fs18.readFile(hookPath, "utf-8");
6003
6075
  if (!content.includes("prjct sync")) continue;
6004
6076
  if (content.includes("Installed by: prjct hooks install")) {
6005
- await fs17.unlink(hookPath);
6077
+ await fs18.unlink(hookPath);
6006
6078
  } else {
6007
6079
  const cleaned = content.split("\n").filter((line) => !line.includes("prjct sync") && !line.includes("prjct auto-sync")).join("\n");
6008
- await fs17.writeFile(hookPath, cleaned, { mode: 493 });
6080
+ await fs18.writeFile(hookPath, cleaned, { mode: 493 });
6009
6081
  }
6010
6082
  }
6011
6083
  return true;
@@ -6231,17 +6303,17 @@ var init_hooks_service = __esm({
6231
6303
  const configFile = await fileExists(path17.join(projectPath, "lefthook.yml")) ? "lefthook.yml" : "lefthook.yaml";
6232
6304
  const configPath = path17.join(projectPath, configFile);
6233
6305
  if (!await fileExists(configPath)) return false;
6234
- const content = await fs17.readFile(configPath, "utf-8");
6306
+ const content = await fs18.readFile(configPath, "utf-8");
6235
6307
  return content.includes(`prjct-sync-${hook}`);
6236
6308
  }
6237
6309
  if (strategy === "husky") {
6238
6310
  const hookPath2 = path17.join(projectPath, ".husky", hook);
6239
6311
  if (!await fileExists(hookPath2)) return false;
6240
- return (await fs17.readFile(hookPath2, "utf-8")).includes("prjct sync");
6312
+ return (await fs18.readFile(hookPath2, "utf-8")).includes("prjct sync");
6241
6313
  }
6242
6314
  const hookPath = path17.join(projectPath, ".git", "hooks", hook);
6243
6315
  if (!await fileExists(hookPath)) return false;
6244
- return (await fs17.readFile(hookPath, "utf-8")).includes("prjct sync");
6316
+ return (await fs18.readFile(hookPath, "utf-8")).includes("prjct sync");
6245
6317
  }
6246
6318
  async getHookPath(projectPath, hook, strategy) {
6247
6319
  if (strategy === "lefthook") {
@@ -6264,7 +6336,7 @@ var init_hooks_service = __esm({
6264
6336
  "project.json"
6265
6337
  );
6266
6338
  if (!await fileExists(projectJsonPath)) return null;
6267
- const project = JSON.parse(await fs17.readFile(projectJsonPath, "utf-8"));
6339
+ const project = JSON.parse(await fs18.readFile(projectJsonPath, "utf-8"));
6268
6340
  return project.hooks || null;
6269
6341
  } catch {
6270
6342
  return null;
@@ -6282,9 +6354,9 @@ var init_hooks_service = __esm({
6282
6354
  "project.json"
6283
6355
  );
6284
6356
  if (!await fileExists(projectJsonPath)) return;
6285
- const project = JSON.parse(await fs17.readFile(projectJsonPath, "utf-8"));
6357
+ const project = JSON.parse(await fs18.readFile(projectJsonPath, "utf-8"));
6286
6358
  project.hooks = config;
6287
- await fs17.writeFile(projectJsonPath, JSON.stringify(project, null, 2));
6359
+ await fs18.writeFile(projectJsonPath, JSON.stringify(project, null, 2));
6288
6360
  } catch {
6289
6361
  }
6290
6362
  }
@@ -6300,7 +6372,7 @@ __export(doctor_service_exports, {
6300
6372
  doctorService: () => doctorService
6301
6373
  });
6302
6374
  import { execSync } from "node:child_process";
6303
- import fs18 from "node:fs/promises";
6375
+ import fs19 from "node:fs/promises";
6304
6376
  import path18 from "node:path";
6305
6377
  import chalk5 from "chalk";
6306
6378
  var DoctorService, doctorService;
@@ -6416,7 +6488,7 @@ var init_doctor_service = __esm({
6416
6488
  async checkPrjctConfig() {
6417
6489
  const configPath = path18.join(this.projectPath, ".prjct", "prjct.config.json");
6418
6490
  try {
6419
- await fs18.access(configPath);
6491
+ await fs19.access(configPath);
6420
6492
  return {
6421
6493
  name: "prjct config",
6422
6494
  status: "ok",
@@ -6440,7 +6512,7 @@ var init_doctor_service = __esm({
6440
6512
  }
6441
6513
  const claudePath = path18.join(this.globalPath, "context", "CLAUDE.md");
6442
6514
  try {
6443
- const stat = await fs18.stat(claudePath);
6515
+ const stat = await fs19.stat(claudePath);
6444
6516
  const ageMs = Date.now() - stat.mtimeMs;
6445
6517
  const ageHours = Math.floor(ageMs / (1e3 * 60 * 60));
6446
6518
  const ageDays = Math.floor(ageHours / 24);
@@ -6514,7 +6586,7 @@ var init_doctor_service = __esm({
6514
6586
  }
6515
6587
  const statePath = path18.join(this.globalPath, "storage", "state.json");
6516
6588
  try {
6517
- const content = await fs18.readFile(statePath, "utf-8");
6589
+ const content = await fs19.readFile(statePath, "utf-8");
6518
6590
  const state = JSON.parse(content);
6519
6591
  if (state.currentTask) {
6520
6592
  return {
@@ -6611,13 +6683,13 @@ var init_doctor_service = __esm({
6611
6683
  });
6612
6684
 
6613
6685
  // core/infrastructure/command-installer.ts
6614
- import fs19 from "node:fs/promises";
6686
+ import fs20 from "node:fs/promises";
6615
6687
  import os6 from "node:os";
6616
6688
  import path19 from "node:path";
6617
6689
  async function loadModuleConfig() {
6618
6690
  try {
6619
6691
  const configPath = path19.join(PACKAGE_ROOT, "templates/global/modules/module-config.json");
6620
- const content = await fs19.readFile(configPath, "utf-8");
6692
+ const content = await fs20.readFile(configPath, "utf-8");
6621
6693
  return JSON.parse(content);
6622
6694
  } catch {
6623
6695
  return null;
@@ -6628,7 +6700,7 @@ async function composeGlobalTemplate(profile) {
6628
6700
  const modulesDir = path19.join(PACKAGE_ROOT, "templates/global/modules");
6629
6701
  if (!config) {
6630
6702
  const legacyPath = path19.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
6631
- return fs19.readFile(legacyPath, "utf-8");
6703
+ return fs20.readFile(legacyPath, "utf-8");
6632
6704
  }
6633
6705
  const profileName = profile || config.default;
6634
6706
  const selectedProfile = config.profiles[profileName];
@@ -6636,7 +6708,7 @@ async function composeGlobalTemplate(profile) {
6636
6708
  const defaultProfile = config.profiles[config.default];
6637
6709
  if (!defaultProfile) {
6638
6710
  const legacyPath = path19.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
6639
- return fs19.readFile(legacyPath, "utf-8");
6711
+ return fs20.readFile(legacyPath, "utf-8");
6640
6712
  }
6641
6713
  }
6642
6714
  const modules = (selectedProfile || config.profiles[config.default]).modules;
@@ -6645,7 +6717,7 @@ async function composeGlobalTemplate(profile) {
6645
6717
  for (const moduleName of modules) {
6646
6718
  try {
6647
6719
  const modulePath = path19.join(modulesDir, moduleName);
6648
- const content = await fs19.readFile(modulePath, "utf-8");
6720
+ const content = await fs20.readFile(modulePath, "utf-8");
6649
6721
  parts.push("");
6650
6722
  parts.push(content);
6651
6723
  } catch {
@@ -6661,14 +6733,14 @@ async function installDocs() {
6661
6733
  try {
6662
6734
  const docsDir = path19.join(os6.homedir(), ".prjct-cli", "docs");
6663
6735
  const templateDocsDir = path19.join(PACKAGE_ROOT, "templates/global/docs");
6664
- await fs19.mkdir(docsDir, { recursive: true });
6665
- const docFiles = await fs19.readdir(templateDocsDir);
6736
+ await fs20.mkdir(docsDir, { recursive: true });
6737
+ const docFiles = await fs20.readdir(templateDocsDir);
6666
6738
  for (const file of docFiles) {
6667
6739
  if (file.endsWith(".md")) {
6668
6740
  const srcPath = path19.join(templateDocsDir, file);
6669
6741
  const destPath = path19.join(docsDir, file);
6670
- const content = await fs19.readFile(srcPath, "utf-8");
6671
- await fs19.writeFile(destPath, content, "utf-8");
6742
+ const content = await fs20.readFile(srcPath, "utf-8");
6743
+ await fs20.writeFile(destPath, content, "utf-8");
6672
6744
  }
6673
6745
  }
6674
6746
  return { success: true };
@@ -6689,23 +6761,23 @@ async function installGlobalConfig2() {
6689
6761
  };
6690
6762
  }
6691
6763
  try {
6692
- await fs19.mkdir(activeProvider.configDir, { recursive: true });
6764
+ await fs20.mkdir(activeProvider.configDir, { recursive: true });
6693
6765
  const globalConfigPath = path19.join(activeProvider.configDir, activeProvider.contextFile);
6694
6766
  const templatePath = path19.join(PACKAGE_ROOT, "templates", "global", activeProvider.contextFile);
6695
6767
  let templateContent = "";
6696
6768
  try {
6697
- templateContent = await fs19.readFile(templatePath, "utf-8");
6769
+ templateContent = await fs20.readFile(templatePath, "utf-8");
6698
6770
  } catch (_error) {
6699
6771
  if (providerName === "claude") {
6700
6772
  try {
6701
6773
  templateContent = await composeGlobalTemplate("standard");
6702
6774
  } catch {
6703
6775
  const fallbackTemplatePath = path19.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
6704
- templateContent = await fs19.readFile(fallbackTemplatePath, "utf-8");
6776
+ templateContent = await fs20.readFile(fallbackTemplatePath, "utf-8");
6705
6777
  }
6706
6778
  } else {
6707
6779
  const fallbackTemplatePath = path19.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
6708
- templateContent = await fs19.readFile(fallbackTemplatePath, "utf-8");
6780
+ templateContent = await fs20.readFile(fallbackTemplatePath, "utf-8");
6709
6781
  if (providerName === "gemini") {
6710
6782
  templateContent = templateContent.replace(/Claude/g, "Gemini");
6711
6783
  }
@@ -6714,7 +6786,7 @@ async function installGlobalConfig2() {
6714
6786
  let existingContent = "";
6715
6787
  let fileExists3 = false;
6716
6788
  try {
6717
- existingContent = await fs19.readFile(globalConfigPath, "utf-8");
6789
+ existingContent = await fs20.readFile(globalConfigPath, "utf-8");
6718
6790
  fileExists3 = true;
6719
6791
  } catch (error) {
6720
6792
  if (isNotFoundError(error)) {
@@ -6724,7 +6796,7 @@ async function installGlobalConfig2() {
6724
6796
  }
6725
6797
  }
6726
6798
  if (!fileExists3) {
6727
- await fs19.writeFile(globalConfigPath, templateContent, "utf-8");
6799
+ await fs20.writeFile(globalConfigPath, templateContent, "utf-8");
6728
6800
  return {
6729
6801
  success: true,
6730
6802
  action: "created",
@@ -6738,7 +6810,7 @@ async function installGlobalConfig2() {
6738
6810
  const updatedContent = `${existingContent}
6739
6811
 
6740
6812
  ${templateContent}`;
6741
- await fs19.writeFile(globalConfigPath, updatedContent, "utf-8");
6813
+ await fs20.writeFile(globalConfigPath, updatedContent, "utf-8");
6742
6814
  return {
6743
6815
  success: true,
6744
6816
  action: "appended",
@@ -6754,7 +6826,7 @@ ${templateContent}`;
6754
6826
  templateContent.indexOf(endMarker) + endMarker.length
6755
6827
  );
6756
6828
  const updatedContent = beforeMarker + prjctSection + afterMarker;
6757
- await fs19.writeFile(globalConfigPath, updatedContent, "utf-8");
6829
+ await fs20.writeFile(globalConfigPath, updatedContent, "utf-8");
6758
6830
  return {
6759
6831
  success: true,
6760
6832
  action: "updated",
@@ -6826,7 +6898,7 @@ var init_command_installer = __esm({
6826
6898
  async detectActiveProvider() {
6827
6899
  await this.ensureInit();
6828
6900
  try {
6829
- await fs19.access(this.claudeConfigPath);
6901
+ await fs20.access(this.claudeConfigPath);
6830
6902
  return true;
6831
6903
  } catch (error) {
6832
6904
  if (isNotFoundError(error)) {
@@ -6846,7 +6918,7 @@ var init_command_installer = __esm({
6846
6918
  */
6847
6919
  async getCommandFiles() {
6848
6920
  try {
6849
- const files = await fs19.readdir(this.templatesDir);
6921
+ const files = await fs20.readdir(this.templatesDir);
6850
6922
  return files.filter((f) => f.endsWith(".md"));
6851
6923
  } catch (_error) {
6852
6924
  return [
@@ -6887,7 +6959,7 @@ var init_command_installer = __esm({
6887
6959
  }
6888
6960
  try {
6889
6961
  await this.installRouter();
6890
- await fs19.mkdir(this.claudeCommandsPath, { recursive: true });
6962
+ await fs20.mkdir(this.claudeCommandsPath, { recursive: true });
6891
6963
  const commandFiles = await this.getCommandFiles();
6892
6964
  const installed = [];
6893
6965
  const errors = [];
@@ -6895,8 +6967,8 @@ var init_command_installer = __esm({
6895
6967
  try {
6896
6968
  const sourcePath = path19.join(this.templatesDir, file);
6897
6969
  const destPath = path19.join(this.claudeCommandsPath, file);
6898
- const content = await fs19.readFile(sourcePath, "utf-8");
6899
- await fs19.writeFile(destPath, content, "utf-8");
6970
+ const content = await fs20.readFile(sourcePath, "utf-8");
6971
+ await fs20.writeFile(destPath, content, "utf-8");
6900
6972
  installed.push(file.replace(".md", ""));
6901
6973
  } catch (error) {
6902
6974
  errors.push({ file, error: getErrorMessage2(error) });
@@ -6926,7 +6998,7 @@ var init_command_installer = __esm({
6926
6998
  for (const file of commandFiles) {
6927
6999
  try {
6928
7000
  const filePath = path19.join(this.claudeCommandsPath, file);
6929
- await fs19.unlink(filePath);
7001
+ await fs20.unlink(filePath);
6930
7002
  uninstalled.push(file.replace(".md", ""));
6931
7003
  } catch (error) {
6932
7004
  if (error.code !== "ENOENT") {
@@ -6935,7 +7007,7 @@ var init_command_installer = __esm({
6935
7007
  }
6936
7008
  }
6937
7009
  try {
6938
- await fs19.rmdir(this.claudeCommandsPath);
7010
+ await fs20.rmdir(this.claudeCommandsPath);
6939
7011
  } catch (_error) {
6940
7012
  }
6941
7013
  return {
@@ -6962,8 +7034,8 @@ var init_command_installer = __esm({
6962
7034
  };
6963
7035
  }
6964
7036
  try {
6965
- await fs19.access(this.claudeCommandsPath);
6966
- const files = await fs19.readdir(this.claudeCommandsPath);
7037
+ await fs20.access(this.claudeCommandsPath);
7038
+ const files = await fs20.readdir(this.claudeCommandsPath);
6967
7039
  const installedCommands = files.filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", ""));
6968
7040
  return {
6969
7041
  installed: installedCommands.length > 0,
@@ -7012,7 +7084,7 @@ var init_command_installer = __esm({
7012
7084
  async verifyTemplate(commandName) {
7013
7085
  try {
7014
7086
  const templatePath = path19.join(this.templatesDir, `${commandName}.md`);
7015
- await fs19.access(templatePath);
7087
+ await fs20.access(templatePath);
7016
7088
  return true;
7017
7089
  } catch (error) {
7018
7090
  if (isNotFoundError(error)) {
@@ -7032,9 +7104,9 @@ var init_command_installer = __esm({
7032
7104
  try {
7033
7105
  const routerSource = path19.join(this.templatesDir, routerFile);
7034
7106
  const routerDest = path19.join(activeProvider.configDir, "commands", routerFile);
7035
- await fs19.mkdir(path19.dirname(routerDest), { recursive: true });
7036
- const content = await fs19.readFile(routerSource, "utf-8");
7037
- await fs19.writeFile(routerDest, content, "utf-8");
7107
+ await fs20.mkdir(path19.dirname(routerDest), { recursive: true });
7108
+ const content = await fs20.readFile(routerSource, "utf-8");
7109
+ await fs20.writeFile(routerDest, content, "utf-8");
7038
7110
  return true;
7039
7111
  } catch (error) {
7040
7112
  if (isNotFoundError(error)) {
@@ -7053,11 +7125,11 @@ var init_command_installer = __esm({
7053
7125
  const commandsRoot = path19.join(activeProvider.configDir, "commands");
7054
7126
  let removed = 0;
7055
7127
  try {
7056
- const files = await fs19.readdir(commandsRoot);
7128
+ const files = await fs20.readdir(commandsRoot);
7057
7129
  const legacyFiles = files.filter((f) => f.startsWith("p.") && f.endsWith(".md"));
7058
7130
  for (const file of legacyFiles) {
7059
7131
  try {
7060
- await fs19.unlink(path19.join(commandsRoot, file));
7132
+ await fs20.unlink(path19.join(commandsRoot, file));
7061
7133
  removed++;
7062
7134
  } catch {
7063
7135
  }
@@ -7082,11 +7154,11 @@ var init_command_installer = __esm({
7082
7154
  }
7083
7155
  try {
7084
7156
  await this.installRouter();
7085
- await fs19.mkdir(this.claudeCommandsPath, { recursive: true });
7157
+ await fs20.mkdir(this.claudeCommandsPath, { recursive: true });
7086
7158
  const templateFiles = await this.getCommandFiles();
7087
7159
  let installedFiles = [];
7088
7160
  try {
7089
- installedFiles = await fs19.readdir(this.claudeCommandsPath);
7161
+ installedFiles = await fs20.readdir(this.claudeCommandsPath);
7090
7162
  installedFiles = installedFiles.filter((f) => f.endsWith(".md"));
7091
7163
  } catch (error) {
7092
7164
  if (isNotFoundError(error)) {
@@ -7107,8 +7179,8 @@ var init_command_installer = __esm({
7107
7179
  const sourcePath = path19.join(this.templatesDir, file);
7108
7180
  const destPath = path19.join(this.claudeCommandsPath, file);
7109
7181
  const exists = installedFiles.includes(file);
7110
- const content = await fs19.readFile(sourcePath, "utf-8");
7111
- await fs19.writeFile(destPath, content, "utf-8");
7182
+ const content = await fs20.readFile(sourcePath, "utf-8");
7183
+ await fs20.writeFile(destPath, content, "utf-8");
7112
7184
  if (!exists) {
7113
7185
  results.added++;
7114
7186
  } else {
@@ -7492,7 +7564,7 @@ var init_chain_of_thought = __esm({
7492
7564
  });
7493
7565
 
7494
7566
  // core/agentic/context-builder.ts
7495
- import fs20 from "node:fs/promises";
7567
+ import fs21 from "node:fs/promises";
7496
7568
  var ContextBuilder, contextBuilder, context_builder_default;
7497
7569
  var init_context_builder = __esm({
7498
7570
  "core/agentic/context-builder.ts"() {
@@ -7571,7 +7643,7 @@ var init_context_builder = __esm({
7571
7643
  for (const [, filePath] of filteredEntries) {
7572
7644
  if (this._cache.has(filePath)) {
7573
7645
  try {
7574
- const stat = await fs20.stat(filePath);
7646
+ const stat = await fs21.stat(filePath);
7575
7647
  const cachedMtime = this._mtimes.get(filePath);
7576
7648
  if (!cachedMtime || stat.mtimeMs > cachedMtime) {
7577
7649
  this._cache.delete(filePath);
@@ -7599,8 +7671,8 @@ var init_context_builder = __esm({
7599
7671
  const readPromises = uncachedEntries.map(async ([key, filePath]) => {
7600
7672
  try {
7601
7673
  const [content, stat] = await Promise.all([
7602
- fs20.readFile(filePath, "utf-8"),
7603
- fs20.stat(filePath)
7674
+ fs21.readFile(filePath, "utf-8"),
7675
+ fs21.stat(filePath)
7604
7676
  ]);
7605
7677
  return { key, filePath, content, mtime: stat.mtimeMs };
7606
7678
  } catch (error) {
@@ -7674,7 +7746,7 @@ var init_context_builder = __esm({
7674
7746
  if (uncachedPaths.length > 0) {
7675
7747
  const readPromises = uncachedPaths.map(async (filePath) => {
7676
7748
  try {
7677
- const content = await fs20.readFile(filePath, "utf-8");
7749
+ const content = await fs21.readFile(filePath, "utf-8");
7678
7750
  return { filePath, content };
7679
7751
  } catch (error) {
7680
7752
  if (isNotFoundError(error)) {
@@ -7708,7 +7780,7 @@ var init_context_builder = __esm({
7708
7780
  */
7709
7781
  async fileExists(filePath) {
7710
7782
  try {
7711
- await fs20.access(filePath);
7783
+ await fs21.access(filePath);
7712
7784
  return true;
7713
7785
  } catch (error) {
7714
7786
  if (isNotFoundError(error)) {
@@ -7735,7 +7807,7 @@ var init_context_builder = __esm({
7735
7807
 
7736
7808
  // core/agentic/ground-truth.ts
7737
7809
  import { exec as exec6 } from "node:child_process";
7738
- import fs21 from "node:fs/promises";
7810
+ import fs22 from "node:fs/promises";
7739
7811
  import os7 from "node:os";
7740
7812
  import path20 from "node:path";
7741
7813
  import { promisify as promisify6 } from "node:util";
@@ -7774,7 +7846,7 @@ async function verifyDone(context2) {
7774
7846
  const actual = {};
7775
7847
  const nowPath = context2.paths.now;
7776
7848
  try {
7777
- const nowContent = await fs21.readFile(nowPath, "utf-8");
7849
+ const nowContent = await fs22.readFile(nowPath, "utf-8");
7778
7850
  actual.nowExists = true;
7779
7851
  actual.nowContent = nowContent.trim();
7780
7852
  actual.nowLength = nowContent.length;
@@ -7802,7 +7874,7 @@ async function verifyDone(context2) {
7802
7874
  }
7803
7875
  const nextPath = context2.paths.next;
7804
7876
  try {
7805
- const nextContent = await fs21.readFile(nextPath, "utf-8");
7877
+ const nextContent = await fs22.readFile(nextPath, "utf-8");
7806
7878
  actual.nextExists = true;
7807
7879
  const tasks = nextContent.match(/- \[ \]/g) || [];
7808
7880
  actual.pendingTasks = tasks.length;
@@ -7816,7 +7888,7 @@ async function verifyDone(context2) {
7816
7888
  }
7817
7889
  const metricsPath = context2.paths.metrics;
7818
7890
  try {
7819
- await fs21.access(path20.dirname(metricsPath), fs21.constants.W_OK);
7891
+ await fs22.access(path20.dirname(metricsPath), fs22.constants.W_OK);
7820
7892
  actual.metricsWritable = true;
7821
7893
  } catch (error) {
7822
7894
  if (isNotFoundError(error)) {
@@ -7852,7 +7924,7 @@ async function verifyShip(context2) {
7852
7924
  }
7853
7925
  const pkgPath = path20.join(context2.projectPath, "package.json");
7854
7926
  try {
7855
- const pkgContent = await fs21.readFile(pkgPath, "utf-8");
7927
+ const pkgContent = await fs22.readFile(pkgPath, "utf-8");
7856
7928
  const pkg = JSON.parse(pkgContent);
7857
7929
  actual.currentVersion = pkg.version;
7858
7930
  actual.hasPackageJson = true;
@@ -7868,7 +7940,7 @@ async function verifyShip(context2) {
7868
7940
  }
7869
7941
  const shippedPath = context2.paths.shipped;
7870
7942
  try {
7871
- const shippedContent = await fs21.readFile(shippedPath, "utf-8");
7943
+ const shippedContent = await fs22.readFile(shippedPath, "utf-8");
7872
7944
  actual.shippedExists = true;
7873
7945
  const featureName = context2.params.feature || context2.params.description;
7874
7946
  if (featureName) {
@@ -7888,7 +7960,7 @@ async function verifyShip(context2) {
7888
7960
  }
7889
7961
  if (actual.hasPackageJson) {
7890
7962
  try {
7891
- const pkgContent = await fs21.readFile(pkgPath, "utf-8");
7963
+ const pkgContent = await fs22.readFile(pkgPath, "utf-8");
7892
7964
  const pkg = JSON.parse(pkgContent);
7893
7965
  actual.hasTestScript = !!pkg.scripts?.test;
7894
7966
  } catch (error) {
@@ -7912,7 +7984,7 @@ async function verifyFeature(context2) {
7912
7984
  const actual = {};
7913
7985
  const nextPath = context2.paths.next;
7914
7986
  try {
7915
- const nextContent = await fs21.readFile(nextPath, "utf-8");
7987
+ const nextContent = await fs22.readFile(nextPath, "utf-8");
7916
7988
  actual.nextExists = true;
7917
7989
  const tasks = nextContent.match(/- \[[ x]\]/g) || [];
7918
7990
  actual.taskCount = tasks.length;
@@ -7931,7 +8003,7 @@ async function verifyFeature(context2) {
7931
8003
  }
7932
8004
  const roadmapPath = context2.paths.roadmap;
7933
8005
  try {
7934
- const roadmapContent = await fs21.readFile(roadmapPath, "utf-8");
8006
+ const roadmapContent = await fs22.readFile(roadmapPath, "utf-8");
7935
8007
  actual.roadmapExists = true;
7936
8008
  const featureName = context2.params.description || context2.params.feature;
7937
8009
  if (featureName) {
@@ -7950,7 +8022,7 @@ async function verifyFeature(context2) {
7950
8022
  }
7951
8023
  const nowPath = context2.paths.now;
7952
8024
  try {
7953
- const nowContent = await fs21.readFile(nowPath, "utf-8");
8025
+ const nowContent = await fs22.readFile(nowPath, "utf-8");
7954
8026
  actual.hasActiveTask = nowContent.trim().length > 0 && !nowContent.includes("No current task");
7955
8027
  if (actual.hasActiveTask) {
7956
8028
  recommendations.push("Consider completing current task first with /p:done");
@@ -7975,7 +8047,7 @@ async function verifyNow(context2) {
7975
8047
  const actual = {};
7976
8048
  const nowPath = context2.paths.now;
7977
8049
  try {
7978
- const nowContent = await fs21.readFile(nowPath, "utf-8");
8050
+ const nowContent = await fs22.readFile(nowPath, "utf-8");
7979
8051
  actual.nowExists = true;
7980
8052
  actual.nowContent = nowContent.trim();
7981
8053
  const hasRealTask = nowContent.trim().length > 0 && !nowContent.includes("No current task") && !nowContent.match(/^#\s*NOW\s*$/m);
@@ -7995,7 +8067,7 @@ async function verifyNow(context2) {
7995
8067
  }
7996
8068
  const nextPath = context2.paths.next;
7997
8069
  try {
7998
- const nextContent = await fs21.readFile(nextPath, "utf-8");
8070
+ const nextContent = await fs22.readFile(nextPath, "utf-8");
7999
8071
  const pendingTasks = (nextContent.match(/- \[ \]/g) || []).length;
8000
8072
  actual.pendingTasks = pendingTasks;
8001
8073
  if (!context2.params.task && pendingTasks > 0) {
@@ -8021,7 +8093,7 @@ async function verifyInit(context2) {
8021
8093
  const actual = {};
8022
8094
  const configPath = path20.join(context2.projectPath, ".prjct/prjct.config.json");
8023
8095
  try {
8024
- const configContent = await fs21.readFile(configPath, "utf-8");
8096
+ const configContent = await fs22.readFile(configPath, "utf-8");
8025
8097
  actual.alreadyInitialized = true;
8026
8098
  actual.existingConfig = JSON.parse(configContent);
8027
8099
  warnings.push("Project already initialized");
@@ -8038,12 +8110,12 @@ async function verifyInit(context2) {
8038
8110
  }
8039
8111
  const globalPath = path20.join(os7.homedir(), ".prjct-cli");
8040
8112
  try {
8041
- await fs21.access(globalPath, fs21.constants.W_OK);
8113
+ await fs22.access(globalPath, fs22.constants.W_OK);
8042
8114
  actual.globalPathWritable = true;
8043
8115
  } catch (error) {
8044
8116
  if (isNotFoundError(error)) {
8045
8117
  try {
8046
- await fs21.mkdir(globalPath, { recursive: true });
8118
+ await fs22.mkdir(globalPath, { recursive: true });
8047
8119
  actual.globalPathWritable = true;
8048
8120
  actual.globalPathCreated = true;
8049
8121
  } catch (_mkdirError) {
@@ -8070,7 +8142,7 @@ async function verifySync(context2) {
8070
8142
  const actual = {};
8071
8143
  const configPath = path20.join(context2.projectPath, ".prjct/prjct.config.json");
8072
8144
  try {
8073
- const configContent = await fs21.readFile(configPath, "utf-8");
8145
+ const configContent = await fs22.readFile(configPath, "utf-8");
8074
8146
  actual.hasConfig = true;
8075
8147
  actual.config = JSON.parse(configContent);
8076
8148
  } catch (error) {
@@ -8091,7 +8163,7 @@ async function verifySync(context2) {
8091
8163
  const projectId = actual.config?.projectId;
8092
8164
  const globalProjectPath = path20.join(os7.homedir(), ".prjct-cli/projects", projectId || "");
8093
8165
  try {
8094
- await fs21.access(globalProjectPath);
8166
+ await fs22.access(globalProjectPath);
8095
8167
  actual.globalStorageExists = true;
8096
8168
  } catch (error) {
8097
8169
  if (isNotFoundError(error)) {
@@ -8117,7 +8189,7 @@ async function verifyAnalyze(context2) {
8117
8189
  actual.detectedFiles = [];
8118
8190
  for (const file of files) {
8119
8191
  try {
8120
- await fs21.access(path20.join(context2.projectPath, file));
8192
+ await fs22.access(path20.join(context2.projectPath, file));
8121
8193
  actual.detectedFiles.push(file);
8122
8194
  } catch (error) {
8123
8195
  if (!isNotFoundError(error)) {
@@ -8133,7 +8205,7 @@ async function verifyAnalyze(context2) {
8133
8205
  actual.detectedSrcDirs = [];
8134
8206
  for (const dir of srcDirs) {
8135
8207
  try {
8136
- const stat = await fs21.stat(path20.join(context2.projectPath, dir));
8208
+ const stat = await fs22.stat(path20.join(context2.projectPath, dir));
8137
8209
  if (stat.isDirectory()) {
8138
8210
  ;
8139
8211
  actual.detectedSrcDirs.push(dir);
@@ -8158,9 +8230,9 @@ async function verifySpec(context2) {
8158
8230
  const actual = {};
8159
8231
  const specsPath = context2.paths.specs;
8160
8232
  try {
8161
- await fs21.access(specsPath);
8233
+ await fs22.access(specsPath);
8162
8234
  actual.specsExists = true;
8163
- const files = await fs21.readdir(specsPath);
8235
+ const files = await fs22.readdir(specsPath);
8164
8236
  actual.existingSpecs = files.filter((f) => f.endsWith(".md"));
8165
8237
  actual.specCount = actual.existingSpecs.length;
8166
8238
  } catch (error) {
@@ -9385,7 +9457,7 @@ var init_shipped = __esm({
9385
9457
  agent: z9.string().optional(),
9386
9458
  // "fe+be", "be", "fe"
9387
9459
  description: z9.string().optional(),
9388
- changes: z9.array(ShipChangeSchema),
9460
+ changes: z9.array(ShipChangeSchema).optional(),
9389
9461
  codeSnippets: z9.array(z9.string()).optional(),
9390
9462
  commit: CommitInfoSchema.optional(),
9391
9463
  codeMetrics: CodeMetricsSchema.optional(),
@@ -9398,7 +9470,7 @@ var init_shipped = __esm({
9398
9470
  featureId: z9.string().optional()
9399
9471
  });
9400
9472
  ShippedJsonSchema = z9.object({
9401
- items: z9.array(ShippedItemSchema),
9473
+ shipped: z9.array(ShippedItemSchema),
9402
9474
  lastUpdated: z9.string()
9403
9475
  });
9404
9476
  }
@@ -9419,7 +9491,8 @@ var init_state = __esm({
9419
9491
  "completed",
9420
9492
  "blocked",
9421
9493
  "paused",
9422
- "failed"
9494
+ "failed",
9495
+ "skipped"
9423
9496
  ]);
9424
9497
  ActivityTypeSchema = z10.enum([
9425
9498
  "task_completed",
@@ -9457,8 +9530,12 @@ var init_state = __esm({
9457
9530
  // ISO8601
9458
9531
  output: z10.string().optional(),
9459
9532
  // Brief output description
9460
- summary: SubtaskSummarySchema.optional()
9533
+ summary: SubtaskSummarySchema.optional(),
9461
9534
  // Full summary for context handoff
9535
+ skipReason: z10.string().optional(),
9536
+ // Why this subtask was skipped
9537
+ blockReason: z10.string().optional()
9538
+ // What is blocking this subtask
9462
9539
  });
9463
9540
  SubtaskProgressSchema = z10.object({
9464
9541
  completed: z10.number(),
@@ -9498,6 +9575,9 @@ var init_state = __esm({
9498
9575
  StateJsonSchema = z10.object({
9499
9576
  currentTask: CurrentTaskSchema.nullable(),
9500
9577
  previousTask: PreviousTaskSchema.nullable().optional(),
9578
+ // deprecated: use pausedTasks
9579
+ pausedTasks: z10.array(PreviousTaskSchema).optional(),
9580
+ // replaces previousTask
9501
9581
  lastUpdated: z10.string()
9502
9582
  });
9503
9583
  QueueTaskSchema = z10.object({
@@ -9592,7 +9672,7 @@ __export(jsonl_helper_exports, {
9592
9672
  writeJsonLines: () => writeJsonLines
9593
9673
  });
9594
9674
  import fsSync from "node:fs";
9595
- import fs22 from "node:fs/promises";
9675
+ import fs23 from "node:fs/promises";
9596
9676
  import path21 from "node:path";
9597
9677
  import readline from "node:readline";
9598
9678
  function parseJsonLines(content) {
@@ -9612,7 +9692,7 @@ function stringifyJsonLines(objects) {
9612
9692
  }
9613
9693
  async function readJsonLines(filePath) {
9614
9694
  try {
9615
- const content = await fs22.readFile(filePath, "utf-8");
9695
+ const content = await fs23.readFile(filePath, "utf-8");
9616
9696
  return parseJsonLines(content);
9617
9697
  } catch (error) {
9618
9698
  if (isNotFoundError(error)) {
@@ -9623,16 +9703,16 @@ async function readJsonLines(filePath) {
9623
9703
  }
9624
9704
  async function writeJsonLines(filePath, objects) {
9625
9705
  const content = stringifyJsonLines(objects);
9626
- await fs22.writeFile(filePath, content, "utf-8");
9706
+ await fs23.writeFile(filePath, content, "utf-8");
9627
9707
  }
9628
9708
  async function appendJsonLine(filePath, object) {
9629
9709
  const line = `${JSON.stringify(object)}
9630
9710
  `;
9631
- await fs22.appendFile(filePath, line, "utf-8");
9711
+ await fs23.appendFile(filePath, line, "utf-8");
9632
9712
  }
9633
9713
  async function appendJsonLines(filePath, objects) {
9634
9714
  const content = stringifyJsonLines(objects);
9635
- await fs22.appendFile(filePath, content, "utf-8");
9715
+ await fs23.appendFile(filePath, content, "utf-8");
9636
9716
  }
9637
9717
  async function filterJsonLines(filePath, predicate) {
9638
9718
  const entries = await readJsonLines(filePath);
@@ -9640,7 +9720,7 @@ async function filterJsonLines(filePath, predicate) {
9640
9720
  }
9641
9721
  async function countJsonLines(filePath) {
9642
9722
  try {
9643
- const content = await fs22.readFile(filePath, "utf-8");
9723
+ const content = await fs23.readFile(filePath, "utf-8");
9644
9724
  const lines = content.split("\n").filter((line) => line.trim());
9645
9725
  return lines.length;
9646
9726
  } catch (error) {
@@ -9699,7 +9779,7 @@ async function readJsonLinesStreaming(filePath, maxLines = STORAGE_LIMITS.JSONL_
9699
9779
  }
9700
9780
  async function getFileSizeMB(filePath) {
9701
9781
  try {
9702
- const stats = await fs22.stat(filePath);
9782
+ const stats = await fs23.stat(filePath);
9703
9783
  return stats.size / (1024 * 1024);
9704
9784
  } catch (error) {
9705
9785
  if (isNotFoundError(error)) {
@@ -9718,7 +9798,7 @@ async function rotateJsonLinesIfNeeded(filePath, maxSizeMB = STORAGE_LIMITS.ROTA
9718
9798
  const ext = path21.extname(filePath);
9719
9799
  const base = path21.basename(filePath, ext);
9720
9800
  const archivePath = path21.join(dir, `${base}-${timestamp}${ext}`);
9721
- await fs22.rename(filePath, archivePath);
9801
+ await fs23.rename(filePath, archivePath);
9722
9802
  console.log(
9723
9803
  `\u{1F4E6} Rotated ${path21.basename(filePath)} (${sizeMB.toFixed(1)}MB) \u2192 ${path21.basename(archivePath)}`
9724
9804
  );
@@ -9798,7 +9878,7 @@ var init_memory = __esm({
9798
9878
  });
9799
9879
 
9800
9880
  // core/agentic/memory-system.ts
9801
- import fs23 from "node:fs/promises";
9881
+ import fs24 from "node:fs/promises";
9802
9882
  import path22 from "node:path";
9803
9883
  var CachedStore, SessionStore, HistoryStore, PatternStore, SemanticMemories, MemorySystem, memorySystem, memory_system_default;
9804
9884
  var init_memory_system = __esm({
@@ -9865,7 +9945,7 @@ var init_memory_system = __esm({
9865
9945
  }
9866
9946
  const filePath = this.getPath(projectId);
9867
9947
  try {
9868
- const content = await fs23.readFile(filePath, "utf-8");
9948
+ const content = await fs24.readFile(filePath, "utf-8");
9869
9949
  this._data = JSON.parse(content);
9870
9950
  this.afterLoad(this._data);
9871
9951
  } catch (error) {
@@ -9901,8 +9981,8 @@ var init_memory_system = __esm({
9901
9981
  async save(projectId) {
9902
9982
  if (!this._data) return;
9903
9983
  const filePath = this.getPath(projectId);
9904
- await fs23.mkdir(path22.dirname(filePath), { recursive: true });
9905
- await fs23.writeFile(filePath, JSON.stringify(this._data, null, 2), "utf-8");
9984
+ await fs24.mkdir(path22.dirname(filePath), { recursive: true });
9985
+ await fs24.writeFile(filePath, JSON.stringify(this._data, null, 2), "utf-8");
9906
9986
  }
9907
9987
  /**
9908
9988
  * Access the cached data without triggering a disk read.
@@ -10691,6 +10771,7 @@ var init_ideas_storage = __esm({
10691
10771
  "core/storage/ideas-storage.ts"() {
10692
10772
  "use strict";
10693
10773
  init_schemas2();
10774
+ init_ideas();
10694
10775
  init_date_helper();
10695
10776
  init_storage_manager();
10696
10777
  IdeasStorage = class extends StorageManager {
@@ -10698,7 +10779,7 @@ var init_ideas_storage = __esm({
10698
10779
  __name(this, "IdeasStorage");
10699
10780
  }
10700
10781
  constructor() {
10701
- super("ideas.json");
10782
+ super("ideas.json", IdeasJsonSchema);
10702
10783
  }
10703
10784
  getDefault() {
10704
10785
  return {
@@ -10891,7 +10972,7 @@ var init_ideas_storage = __esm({
10891
10972
 
10892
10973
  // core/storage/index-storage.ts
10893
10974
  import crypto4 from "node:crypto";
10894
- import fs24 from "node:fs/promises";
10975
+ import fs25 from "node:fs/promises";
10895
10976
  import path23 from "node:path";
10896
10977
  function getDefaultChecksums() {
10897
10978
  return {
@@ -10924,7 +11005,7 @@ var init_index_storage = __esm({
10924
11005
  */
10925
11006
  async ensureIndexDir(projectId) {
10926
11007
  const indexPath = this.getIndexPath(projectId);
10927
- await fs24.mkdir(indexPath, { recursive: true });
11008
+ await fs25.mkdir(indexPath, { recursive: true });
10928
11009
  return indexPath;
10929
11010
  }
10930
11011
  // ==========================================================================
@@ -10936,7 +11017,7 @@ var init_index_storage = __esm({
10936
11017
  async readIndex(projectId) {
10937
11018
  const filePath = path23.join(this.getIndexPath(projectId), "project-index.json");
10938
11019
  try {
10939
- const content = await fs24.readFile(filePath, "utf-8");
11020
+ const content = await fs25.readFile(filePath, "utf-8");
10940
11021
  const index = JSON.parse(content);
10941
11022
  if (index.version !== INDEX_VERSION) {
10942
11023
  return null;
@@ -10955,7 +11036,7 @@ var init_index_storage = __esm({
10955
11036
  async writeIndex(projectId, index) {
10956
11037
  await this.ensureIndexDir(projectId);
10957
11038
  const filePath = path23.join(this.getIndexPath(projectId), "project-index.json");
10958
- await fs24.writeFile(filePath, JSON.stringify(index, null, 2), "utf-8");
11039
+ await fs25.writeFile(filePath, JSON.stringify(index, null, 2), "utf-8");
10959
11040
  }
10960
11041
  /**
10961
11042
  * Check if index exists and is valid
@@ -10973,7 +11054,7 @@ var init_index_storage = __esm({
10973
11054
  async readChecksums(projectId) {
10974
11055
  const filePath = path23.join(this.getIndexPath(projectId), "checksums.json");
10975
11056
  try {
10976
- const content = await fs24.readFile(filePath, "utf-8");
11057
+ const content = await fs25.readFile(filePath, "utf-8");
10977
11058
  return JSON.parse(content);
10978
11059
  } catch (error) {
10979
11060
  if (isNotFoundError(error)) {
@@ -10988,14 +11069,14 @@ var init_index_storage = __esm({
10988
11069
  async writeChecksums(projectId, checksums) {
10989
11070
  await this.ensureIndexDir(projectId);
10990
11071
  const filePath = path23.join(this.getIndexPath(projectId), "checksums.json");
10991
- await fs24.writeFile(filePath, JSON.stringify(checksums, null, 2), "utf-8");
11072
+ await fs25.writeFile(filePath, JSON.stringify(checksums, null, 2), "utf-8");
10992
11073
  }
10993
11074
  /**
10994
11075
  * Calculate checksum for a file
10995
11076
  */
10996
11077
  async calculateChecksum(filePath) {
10997
11078
  try {
10998
- const content = await fs24.readFile(filePath);
11079
+ const content = await fs25.readFile(filePath);
10999
11080
  return crypto4.createHash("md5").update(content).digest("hex");
11000
11081
  } catch {
11001
11082
  return "";
@@ -11033,7 +11114,7 @@ var init_index_storage = __esm({
11033
11114
  async readScores(projectId) {
11034
11115
  const filePath = path23.join(this.getIndexPath(projectId), "file-scores.json");
11035
11116
  try {
11036
- const content = await fs24.readFile(filePath, "utf-8");
11117
+ const content = await fs25.readFile(filePath, "utf-8");
11037
11118
  const data = JSON.parse(content);
11038
11119
  return data.scores || [];
11039
11120
  } catch (error) {
@@ -11054,7 +11135,7 @@ var init_index_storage = __esm({
11054
11135
  lastUpdated: getTimestamp(),
11055
11136
  scores
11056
11137
  };
11057
- await fs24.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
11138
+ await fs25.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
11058
11139
  }
11059
11140
  // ==========================================================================
11060
11141
  // UTILITY METHODS
@@ -11065,8 +11146,8 @@ var init_index_storage = __esm({
11065
11146
  async clearIndex(projectId) {
11066
11147
  const indexPath = this.getIndexPath(projectId);
11067
11148
  try {
11068
- const files = await fs24.readdir(indexPath);
11069
- await Promise.all(files.map((file) => fs24.unlink(path23.join(indexPath, file))));
11149
+ const files = await fs25.readdir(indexPath);
11150
+ await Promise.all(files.map((file) => fs25.unlink(path23.join(indexPath, file))));
11070
11151
  } catch (error) {
11071
11152
  if (!isNotFoundError(error)) {
11072
11153
  throw error;
@@ -11094,7 +11175,7 @@ var init_index_storage = __esm({
11094
11175
  async readDomains(projectId) {
11095
11176
  const filePath = path23.join(this.getIndexPath(projectId), "domains.json");
11096
11177
  try {
11097
- const content = await fs24.readFile(filePath, "utf-8");
11178
+ const content = await fs25.readFile(filePath, "utf-8");
11098
11179
  const domains = JSON.parse(content);
11099
11180
  if (domains.version !== INDEX_VERSION) {
11100
11181
  return null;
@@ -11113,7 +11194,7 @@ var init_index_storage = __esm({
11113
11194
  async writeDomains(projectId, domains) {
11114
11195
  await this.ensureIndexDir(projectId);
11115
11196
  const filePath = path23.join(this.getIndexPath(projectId), "domains.json");
11116
- await fs24.writeFile(filePath, JSON.stringify(domains, null, 2), "utf-8");
11197
+ await fs25.writeFile(filePath, JSON.stringify(domains, null, 2), "utf-8");
11117
11198
  }
11118
11199
  // ==========================================================================
11119
11200
  // CATEGORIES CACHE
@@ -11124,7 +11205,7 @@ var init_index_storage = __esm({
11124
11205
  async readCategories(projectId) {
11125
11206
  const filePath = path23.join(this.getIndexPath(projectId), "categories-cache.json");
11126
11207
  try {
11127
- const content = await fs24.readFile(filePath, "utf-8");
11208
+ const content = await fs25.readFile(filePath, "utf-8");
11128
11209
  const cache2 = JSON.parse(content);
11129
11210
  if (cache2.version !== INDEX_VERSION) {
11130
11211
  return null;
@@ -11143,7 +11224,7 @@ var init_index_storage = __esm({
11143
11224
  async writeCategories(projectId, cache2) {
11144
11225
  await this.ensureIndexDir(projectId);
11145
11226
  const filePath = path23.join(this.getIndexPath(projectId), "categories-cache.json");
11146
- await fs24.writeFile(filePath, JSON.stringify(cache2, null, 2), "utf-8");
11227
+ await fs25.writeFile(filePath, JSON.stringify(cache2, null, 2), "utf-8");
11147
11228
  }
11148
11229
  /**
11149
11230
  * Get file categories for specific paths
@@ -11183,6 +11264,7 @@ var init_queue_storage = __esm({
11183
11264
  "core/storage/queue-storage.ts"() {
11184
11265
  "use strict";
11185
11266
  init_schemas2();
11267
+ init_state();
11186
11268
  init_date_helper();
11187
11269
  init_storage_manager();
11188
11270
  QueueStorage = class extends StorageManager {
@@ -11190,7 +11272,7 @@ var init_queue_storage = __esm({
11190
11272
  __name(this, "QueueStorage");
11191
11273
  }
11192
11274
  constructor() {
11193
- super("queue.json");
11275
+ super("queue.json", QueueJsonSchema);
11194
11276
  }
11195
11277
  getDefault() {
11196
11278
  return {
@@ -11423,6 +11505,7 @@ var init_shipped_storage = __esm({
11423
11505
  "core/storage/shipped-storage.ts"() {
11424
11506
  "use strict";
11425
11507
  init_schemas2();
11508
+ init_shipped();
11426
11509
  init_date_helper();
11427
11510
  init_storage_manager();
11428
11511
  ShippedStorage = class extends StorageManager {
@@ -11430,7 +11513,7 @@ var init_shipped_storage = __esm({
11430
11513
  __name(this, "ShippedStorage");
11431
11514
  }
11432
11515
  constructor() {
11433
- super("shipped.json");
11516
+ super("shipped.json", ShippedJsonSchema);
11434
11517
  }
11435
11518
  getDefault() {
11436
11519
  return {
@@ -11817,21 +11900,172 @@ var init_markdown_builder = __esm({
11817
11900
  }
11818
11901
  });
11819
11902
 
11903
+ // core/workflow/state-machine.ts
11904
+ var WORKFLOW_STATES, WorkflowStateMachine, workflowStateMachine;
11905
+ var init_state_machine = __esm({
11906
+ "core/workflow/state-machine.ts"() {
11907
+ "use strict";
11908
+ WORKFLOW_STATES = {
11909
+ idle: {
11910
+ transitions: ["task", "next"],
11911
+ prompt: "p. task <description> Start working",
11912
+ description: "No active task"
11913
+ },
11914
+ working: {
11915
+ transitions: ["done", "pause"],
11916
+ prompt: "p. done Complete task | p. pause Switch context",
11917
+ description: "Task in progress"
11918
+ },
11919
+ paused: {
11920
+ transitions: ["resume", "task", "ship"],
11921
+ prompt: "p. resume Continue | p. task <new> Start different | p. ship Ship directly",
11922
+ description: "Task paused"
11923
+ },
11924
+ completed: {
11925
+ transitions: ["ship", "task", "next", "pause", "reopen"],
11926
+ prompt: "p. ship Ship it | p. task <next> Start next | p. reopen Reopen for rework",
11927
+ description: "Task completed"
11928
+ },
11929
+ shipped: {
11930
+ transitions: ["task", "next"],
11931
+ prompt: "p. task <description> Start new task",
11932
+ description: "Feature shipped"
11933
+ }
11934
+ };
11935
+ WorkflowStateMachine = class {
11936
+ static {
11937
+ __name(this, "WorkflowStateMachine");
11938
+ }
11939
+ /**
11940
+ * Get current state from storage state
11941
+ */
11942
+ getCurrentState(storageState) {
11943
+ const task = storageState?.currentTask;
11944
+ if (!task) {
11945
+ const hasPaused = (storageState?.pausedTasks?.length || 0) > 0 || storageState?.previousTask?.status === "paused";
11946
+ return hasPaused ? "paused" : "idle";
11947
+ }
11948
+ const status = (typeof task.status === "string" ? task.status : "").toLowerCase();
11949
+ switch (status) {
11950
+ case "in_progress":
11951
+ case "working":
11952
+ return "working";
11953
+ case "paused":
11954
+ return "paused";
11955
+ case "completed":
11956
+ case "done":
11957
+ return "completed";
11958
+ case "shipped":
11959
+ return "shipped";
11960
+ default:
11961
+ return task ? "working" : "idle";
11962
+ }
11963
+ }
11964
+ /**
11965
+ * Check if a command is valid for the current state
11966
+ */
11967
+ canTransition(currentState, command) {
11968
+ const stateConfig = WORKFLOW_STATES[currentState];
11969
+ if (stateConfig.transitions.includes(command)) {
11970
+ return { valid: true };
11971
+ }
11972
+ const validCommands = stateConfig.transitions.map((c) => `p. ${c}`).join(", ");
11973
+ return {
11974
+ valid: false,
11975
+ error: `Cannot run 'p. ${command}' in ${currentState} state`,
11976
+ suggestion: `Valid commands: ${validCommands}`
11977
+ };
11978
+ }
11979
+ /**
11980
+ * Get the next state after a command
11981
+ */
11982
+ getNextState(currentState, command) {
11983
+ switch (command) {
11984
+ case "task":
11985
+ return "working";
11986
+ case "done":
11987
+ return "completed";
11988
+ case "pause":
11989
+ return "paused";
11990
+ case "resume":
11991
+ return "working";
11992
+ case "ship":
11993
+ return "shipped";
11994
+ case "reopen":
11995
+ return "working";
11996
+ case "next":
11997
+ return currentState;
11998
+ // next doesn't change state
11999
+ default:
12000
+ return currentState;
12001
+ }
12002
+ }
12003
+ /**
12004
+ * Get state definition
12005
+ */
12006
+ getStateInfo(state) {
12007
+ return WORKFLOW_STATES[state];
12008
+ }
12009
+ /**
12010
+ * Get prompt for current state
12011
+ */
12012
+ getPrompt(state) {
12013
+ return WORKFLOW_STATES[state].prompt;
12014
+ }
12015
+ /**
12016
+ * Get valid commands for current state
12017
+ */
12018
+ getValidCommands(state) {
12019
+ return WORKFLOW_STATES[state].transitions;
12020
+ }
12021
+ /**
12022
+ * Format next steps for display
12023
+ */
12024
+ formatNextSteps(state) {
12025
+ const stateConfig = WORKFLOW_STATES[state];
12026
+ return stateConfig.transitions.map((cmd) => {
12027
+ switch (cmd) {
12028
+ case "task":
12029
+ return "p. task <desc> Start new task";
12030
+ case "done":
12031
+ return "p. done Complete current task";
12032
+ case "pause":
12033
+ return "p. pause Pause and switch context";
12034
+ case "resume":
12035
+ return "p. resume Continue paused task";
12036
+ case "ship":
12037
+ return "p. ship Ship the feature";
12038
+ case "reopen":
12039
+ return "p. reopen Reopen for rework";
12040
+ case "next":
12041
+ return "p. next View task queue";
12042
+ default:
12043
+ return `p. ${cmd}`;
12044
+ }
12045
+ });
12046
+ }
12047
+ };
12048
+ workflowStateMachine = new WorkflowStateMachine();
12049
+ }
12050
+ });
12051
+
11820
12052
  // core/storage/state-storage.ts
11821
12053
  var StateStorage, stateStorage;
11822
12054
  var init_state_storage = __esm({
11823
12055
  "core/storage/state-storage.ts"() {
11824
12056
  "use strict";
11825
12057
  init_schemas2();
12058
+ init_state();
11826
12059
  init_date_helper();
11827
12060
  init_markdown_builder();
12061
+ init_state_machine();
11828
12062
  init_storage_manager();
11829
12063
  StateStorage = class extends StorageManager {
11830
12064
  static {
11831
12065
  __name(this, "StateStorage");
11832
12066
  }
11833
12067
  constructor() {
11834
- super("state.json");
12068
+ super("state.json", StateJsonSchema);
11835
12069
  }
11836
12070
  getDefault() {
11837
12071
  return {
@@ -11858,7 +12092,7 @@ var init_state_storage = __esm({
11858
12092
  `**Progress**: ${task.subtaskProgress?.completed || 0}/${task.subtaskProgress?.total || 0} (${task.subtaskProgress?.percentage || 0}%)`
11859
12093
  ).blank().raw("| # | Domain | Description | Status | Agent |").raw("|---|--------|-------------|--------|-------|");
11860
12094
  task.subtasks.forEach((subtask, index) => {
11861
- const statusIcon = subtask.status === "completed" ? "\u2705" : subtask.status === "in_progress" ? "\u25B6\uFE0F" : subtask.status === "failed" ? "\u274C" : "\u23F3";
12095
+ const statusIcon = subtask.status === "completed" ? "\u2705" : subtask.status === "in_progress" ? "\u25B6\uFE0F" : subtask.status === "failed" ? "\u274C" : subtask.status === "skipped" ? "\u23ED\uFE0F" : subtask.status === "blocked" ? "\u{1F6AB}" : "\u23F3";
11862
12096
  const isActive = index === task.currentSubtaskIndex ? " **\u2190 Active**" : "";
11863
12097
  m.raw(
11864
12098
  `| ${index + 1} | ${subtask.domain} | ${subtask.description} | ${statusIcon} ${subtask.status}${isActive} | ${subtask.agent} |`
@@ -11886,10 +12120,29 @@ var init_state_storage = __esm({
11886
12120
  }
11887
12121
  }).when(!data.currentTask, (m) => {
11888
12122
  m.italic("No active task. Use /p:work to start.");
11889
- }).maybe(data.previousTask, (m, prev) => {
11890
- m.hr().h2("Paused").bold(prev.description).raw(`Paused: ${toRelative(prev.pausedAt)}`).maybe(prev.pauseReason, (m2, reason2) => m2.raw(`Reason: ${reason2}`)).blank().italic("Use /p:resume to continue");
12123
+ }).when((data.pausedTasks?.length || 0) > 0 || !!data.previousTask, (m) => {
12124
+ const paused = data.pausedTasks?.length ? data.pausedTasks : data.previousTask ? [data.previousTask] : [];
12125
+ if (paused.length === 0) return;
12126
+ m.hr().h2(`Paused (${paused.length})`);
12127
+ paused.forEach((prev, i) => {
12128
+ m.raw(`${i + 1}. **${prev.description}**`).raw(` Paused: ${toRelative(prev.pausedAt)}`);
12129
+ if (prev.pauseReason) m.raw(` Reason: ${prev.pauseReason}`);
12130
+ });
12131
+ m.blank().italic("Use /p:resume to continue");
11891
12132
  }).blank().build();
11892
12133
  }
12134
+ // =========== Transition Validation ===========
12135
+ /**
12136
+ * Validate a state transition through the state machine.
12137
+ * Throws if the transition is invalid.
12138
+ */
12139
+ validateTransition(state, command) {
12140
+ const currentState = workflowStateMachine.getCurrentState(state);
12141
+ const result = workflowStateMachine.canTransition(currentState, command);
12142
+ if (!result.valid) {
12143
+ throw new Error(`${result.error}. ${result.suggestion || ""}`.trim());
12144
+ }
12145
+ }
11893
12146
  // =========== Domain Methods ===========
11894
12147
  /**
11895
12148
  * Get current active task
@@ -11902,12 +12155,14 @@ var init_state_storage = __esm({
11902
12155
  * Start a new task
11903
12156
  */
11904
12157
  async startTask(projectId, task) {
12158
+ const state = await this.read(projectId);
12159
+ this.validateTransition(state, "task");
11905
12160
  const currentTask = {
11906
12161
  ...task,
11907
12162
  startedAt: getTimestamp()
11908
12163
  };
11909
- await this.update(projectId, (state) => ({
11910
- ...state,
12164
+ await this.update(projectId, (state2) => ({
12165
+ ...state2,
11911
12166
  currentTask,
11912
12167
  lastUpdated: getTimestamp()
11913
12168
  }));
@@ -11928,6 +12183,7 @@ var init_state_storage = __esm({
11928
12183
  if (!completedTask) {
11929
12184
  return null;
11930
12185
  }
12186
+ this.validateTransition(state, "done");
11931
12187
  await this.update(projectId, () => ({
11932
12188
  currentTask: null,
11933
12189
  previousTask: null,
@@ -11941,15 +12197,20 @@ var init_state_storage = __esm({
11941
12197
  });
11942
12198
  return completedTask;
11943
12199
  }
12200
+ /** Max number of paused tasks (configurable) */
12201
+ maxPausedTasks = 5;
12202
+ /** Staleness threshold in days */
12203
+ stalenessThresholdDays = 30;
11944
12204
  /**
11945
- * Pause current task
12205
+ * Pause current task — pushes onto pausedTasks[] array
11946
12206
  */
11947
12207
  async pauseTask(projectId, reason2) {
11948
12208
  const state = await this.read(projectId);
11949
12209
  if (!state.currentTask) {
11950
12210
  return null;
11951
12211
  }
11952
- const previousTask = {
12212
+ this.validateTransition(state, "pause");
12213
+ const pausedTask = {
11953
12214
  id: state.currentTask.id,
11954
12215
  description: state.currentTask.description,
11955
12216
  status: "paused",
@@ -11957,45 +12218,111 @@ var init_state_storage = __esm({
11957
12218
  pausedAt: getTimestamp(),
11958
12219
  pauseReason: reason2
11959
12220
  };
12221
+ const existingPaused = this.getPausedTasksFromState(state);
12222
+ const pausedTasks = [pausedTask, ...existingPaused].slice(0, this.maxPausedTasks);
11960
12223
  await this.update(projectId, () => ({
11961
12224
  currentTask: null,
11962
- previousTask,
12225
+ previousTask: null,
12226
+ // deprecated, keep null for compat
12227
+ pausedTasks,
11963
12228
  lastUpdated: getTimestamp()
11964
12229
  }));
11965
12230
  await this.publishEvent(projectId, "task.paused", {
11966
- taskId: previousTask.id,
11967
- description: previousTask.description,
11968
- pausedAt: previousTask.pausedAt,
11969
- reason: reason2
12231
+ taskId: pausedTask.id,
12232
+ description: pausedTask.description,
12233
+ pausedAt: pausedTask.pausedAt,
12234
+ reason: reason2,
12235
+ pausedCount: pausedTasks.length
11970
12236
  });
11971
- return previousTask;
12237
+ return pausedTask;
11972
12238
  }
11973
12239
  /**
11974
- * Resume paused task
12240
+ * Resume most recent paused task (or by ID)
11975
12241
  */
11976
- async resumeTask(projectId) {
12242
+ async resumeTask(projectId, taskId) {
11977
12243
  const state = await this.read(projectId);
11978
- if (!state.previousTask) {
12244
+ const pausedTasks = this.getPausedTasksFromState(state);
12245
+ if (pausedTasks.length === 0) {
11979
12246
  return null;
11980
12247
  }
12248
+ this.validateTransition(state, "resume");
12249
+ let targetIndex = 0;
12250
+ if (taskId) {
12251
+ targetIndex = pausedTasks.findIndex((t) => t.id === taskId);
12252
+ if (targetIndex === -1) return null;
12253
+ }
12254
+ const target = pausedTasks[targetIndex];
12255
+ const remaining = pausedTasks.filter((_, i) => i !== targetIndex);
11981
12256
  const currentTask = {
11982
- id: state.previousTask.id,
11983
- description: state.previousTask.description,
12257
+ id: target.id,
12258
+ description: target.description,
11984
12259
  startedAt: getTimestamp(),
11985
12260
  sessionId: generateUUID()
11986
12261
  };
11987
12262
  await this.update(projectId, () => ({
11988
12263
  currentTask,
11989
12264
  previousTask: null,
12265
+ // deprecated, keep null
12266
+ pausedTasks: remaining,
11990
12267
  lastUpdated: getTimestamp()
11991
12268
  }));
11992
12269
  await this.publishEvent(projectId, "task.resumed", {
11993
12270
  taskId: currentTask.id,
11994
12271
  description: currentTask.description,
11995
- resumedAt: currentTask.startedAt
12272
+ resumedAt: currentTask.startedAt,
12273
+ remainingPaused: remaining.length
11996
12274
  });
11997
12275
  return currentTask;
11998
12276
  }
12277
+ /**
12278
+ * Get paused tasks from state, migrating from legacy previousTask if needed
12279
+ */
12280
+ getPausedTasksFromState(state) {
12281
+ const paused = state.pausedTasks || [];
12282
+ if (state.previousTask && state.previousTask.status === "paused") {
12283
+ const alreadyInArray = paused.some((t) => t.id === state.previousTask.id);
12284
+ if (!alreadyInArray) {
12285
+ return [state.previousTask, ...paused];
12286
+ }
12287
+ }
12288
+ return paused;
12289
+ }
12290
+ /**
12291
+ * Get stale paused tasks (older than threshold)
12292
+ */
12293
+ async getStalePausedTasks(projectId) {
12294
+ const state = await this.read(projectId);
12295
+ const pausedTasks = this.getPausedTasksFromState(state);
12296
+ const threshold = Date.now() - this.stalenessThresholdDays * 24 * 60 * 60 * 1e3;
12297
+ return pausedTasks.filter((t) => new Date(t.pausedAt).getTime() < threshold);
12298
+ }
12299
+ /**
12300
+ * Archive stale paused tasks (remove from pausedTasks)
12301
+ * Returns archived tasks
12302
+ */
12303
+ async archiveStalePausedTasks(projectId) {
12304
+ const state = await this.read(projectId);
12305
+ const pausedTasks = this.getPausedTasksFromState(state);
12306
+ const threshold = Date.now() - this.stalenessThresholdDays * 24 * 60 * 60 * 1e3;
12307
+ const stale = pausedTasks.filter((t) => new Date(t.pausedAt).getTime() < threshold);
12308
+ const fresh = pausedTasks.filter((t) => new Date(t.pausedAt).getTime() >= threshold);
12309
+ if (stale.length === 0) return [];
12310
+ await this.update(projectId, (s) => ({
12311
+ ...s,
12312
+ pausedTasks: fresh,
12313
+ previousTask: null,
12314
+ lastUpdated: getTimestamp()
12315
+ }));
12316
+ for (const task of stale) {
12317
+ await this.publishEvent(projectId, "task.archived", {
12318
+ taskId: task.id,
12319
+ description: task.description,
12320
+ pausedAt: task.pausedAt,
12321
+ reason: "staleness"
12322
+ });
12323
+ }
12324
+ return stale;
12325
+ }
11999
12326
  /**
12000
12327
  * Clear all task state
12001
12328
  */
@@ -12003,6 +12330,7 @@ var init_state_storage = __esm({
12003
12330
  await this.update(projectId, () => ({
12004
12331
  currentTask: null,
12005
12332
  previousTask: null,
12333
+ pausedTasks: [],
12006
12334
  lastUpdated: getTimestamp()
12007
12335
  }));
12008
12336
  }
@@ -12011,14 +12339,23 @@ var init_state_storage = __esm({
12011
12339
  */
12012
12340
  async hasTask(projectId) {
12013
12341
  const state = await this.read(projectId);
12014
- return state.currentTask !== null || state.previousTask !== null;
12342
+ const paused = this.getPausedTasksFromState(state);
12343
+ return state.currentTask !== null || paused.length > 0;
12015
12344
  }
12016
12345
  /**
12017
- * Get paused task
12346
+ * Get most recently paused task
12018
12347
  */
12019
12348
  async getPausedTask(projectId) {
12020
12349
  const state = await this.read(projectId);
12021
- return state.previousTask || null;
12350
+ const paused = this.getPausedTasksFromState(state);
12351
+ return paused[0] || null;
12352
+ }
12353
+ /**
12354
+ * Get all paused tasks
12355
+ */
12356
+ async getAllPausedTasks(projectId) {
12357
+ const state = await this.read(projectId);
12358
+ return this.getPausedTasksFromState(state);
12022
12359
  }
12023
12360
  // =========== Subtask Methods ===========
12024
12361
  /**
@@ -12158,41 +12495,152 @@ var init_state_storage = __esm({
12158
12495
  /**
12159
12496
  * Check if all subtasks are complete
12160
12497
  */
12161
- async areAllSubtasksComplete(projectId) {
12498
+ async areAllSubtasksComplete(projectId) {
12499
+ const state = await this.read(projectId);
12500
+ if (!state.currentTask?.subtasks) return true;
12501
+ return state.currentTask.subtasks.every(
12502
+ (s) => s.status === "completed" || s.status === "failed" || s.status === "skipped"
12503
+ );
12504
+ }
12505
+ /**
12506
+ * Fail current subtask and advance to next
12507
+ * Returns the next subtask (or null if all done/failed)
12508
+ */
12509
+ async failSubtask(projectId, error) {
12510
+ const state = await this.read(projectId);
12511
+ if (!state.currentTask?.subtasks) return null;
12512
+ const currentIndex = state.currentTask.currentSubtaskIndex || 0;
12513
+ const current = state.currentTask.subtasks[currentIndex];
12514
+ if (!current) return null;
12515
+ const updatedSubtasks = [...state.currentTask.subtasks];
12516
+ updatedSubtasks[currentIndex] = {
12517
+ ...current,
12518
+ status: "failed",
12519
+ completedAt: getTimestamp(),
12520
+ output: `Failed: ${error}`
12521
+ };
12522
+ const nextIndex = currentIndex + 1;
12523
+ const total = updatedSubtasks.length;
12524
+ if (nextIndex < total) {
12525
+ updatedSubtasks[nextIndex] = {
12526
+ ...updatedSubtasks[nextIndex],
12527
+ status: "in_progress",
12528
+ startedAt: getTimestamp()
12529
+ };
12530
+ }
12531
+ const resolved = updatedSubtasks.filter(
12532
+ (s) => s.status === "completed" || s.status === "failed" || s.status === "skipped"
12533
+ ).length;
12534
+ const percentage = Math.round(resolved / total * 100);
12535
+ await this.update(projectId, (s) => ({
12536
+ ...s,
12537
+ currentTask: {
12538
+ ...s.currentTask,
12539
+ subtasks: updatedSubtasks,
12540
+ currentSubtaskIndex: nextIndex < total ? nextIndex : currentIndex,
12541
+ subtaskProgress: { completed: resolved, total, percentage }
12542
+ },
12543
+ lastUpdated: getTimestamp()
12544
+ }));
12545
+ await this.publishEvent(projectId, "subtask.failed", {
12546
+ taskId: state.currentTask.id,
12547
+ subtaskId: current.id,
12548
+ description: current.description,
12549
+ error
12550
+ });
12551
+ return nextIndex < total ? updatedSubtasks[nextIndex] : null;
12552
+ }
12553
+ /**
12554
+ * Skip current subtask with reason and advance to next
12555
+ * Returns the next subtask (or null if all done)
12556
+ */
12557
+ async skipSubtask(projectId, reason2) {
12162
12558
  const state = await this.read(projectId);
12163
- if (!state.currentTask?.subtasks) return true;
12164
- return state.currentTask.subtasks.every((s) => s.status === "completed");
12559
+ if (!state.currentTask?.subtasks) return null;
12560
+ const currentIndex = state.currentTask.currentSubtaskIndex || 0;
12561
+ const current = state.currentTask.subtasks[currentIndex];
12562
+ if (!current) return null;
12563
+ const updatedSubtasks = [...state.currentTask.subtasks];
12564
+ updatedSubtasks[currentIndex] = {
12565
+ ...current,
12566
+ status: "skipped",
12567
+ completedAt: getTimestamp(),
12568
+ output: `Skipped: ${reason2}`,
12569
+ skipReason: reason2
12570
+ };
12571
+ const nextIndex = currentIndex + 1;
12572
+ const total = updatedSubtasks.length;
12573
+ if (nextIndex < total) {
12574
+ updatedSubtasks[nextIndex] = {
12575
+ ...updatedSubtasks[nextIndex],
12576
+ status: "in_progress",
12577
+ startedAt: getTimestamp()
12578
+ };
12579
+ }
12580
+ const resolved = updatedSubtasks.filter(
12581
+ (s) => s.status === "completed" || s.status === "failed" || s.status === "skipped"
12582
+ ).length;
12583
+ const percentage = Math.round(resolved / total * 100);
12584
+ await this.update(projectId, (s) => ({
12585
+ ...s,
12586
+ currentTask: {
12587
+ ...s.currentTask,
12588
+ subtasks: updatedSubtasks,
12589
+ currentSubtaskIndex: nextIndex < total ? nextIndex : currentIndex,
12590
+ subtaskProgress: { completed: resolved, total, percentage }
12591
+ },
12592
+ lastUpdated: getTimestamp()
12593
+ }));
12594
+ await this.publishEvent(projectId, "subtask.skipped", {
12595
+ taskId: state.currentTask.id,
12596
+ subtaskId: current.id,
12597
+ description: current.description,
12598
+ reason: reason2
12599
+ });
12600
+ return nextIndex < total ? updatedSubtasks[nextIndex] : null;
12165
12601
  }
12166
12602
  /**
12167
- * Fail current subtask
12603
+ * Block current subtask with reason, allow proceeding to next
12604
+ * Returns the next subtask (or null if no more)
12168
12605
  */
12169
- async failSubtask(projectId, error) {
12606
+ async blockSubtask(projectId, blocker) {
12170
12607
  const state = await this.read(projectId);
12171
- if (!state.currentTask?.subtasks) return;
12608
+ if (!state.currentTask?.subtasks) return null;
12172
12609
  const currentIndex = state.currentTask.currentSubtaskIndex || 0;
12173
12610
  const current = state.currentTask.subtasks[currentIndex];
12174
- if (!current) return;
12611
+ if (!current) return null;
12175
12612
  const updatedSubtasks = [...state.currentTask.subtasks];
12176
12613
  updatedSubtasks[currentIndex] = {
12177
12614
  ...current,
12178
- status: "failed",
12179
- completedAt: getTimestamp(),
12180
- output: `Failed: ${error}`
12615
+ status: "blocked",
12616
+ output: `Blocked: ${blocker}`,
12617
+ blockReason: blocker
12181
12618
  };
12619
+ const nextIndex = currentIndex + 1;
12620
+ const total = updatedSubtasks.length;
12621
+ if (nextIndex < total) {
12622
+ updatedSubtasks[nextIndex] = {
12623
+ ...updatedSubtasks[nextIndex],
12624
+ status: "in_progress",
12625
+ startedAt: getTimestamp()
12626
+ };
12627
+ }
12182
12628
  await this.update(projectId, (s) => ({
12183
12629
  ...s,
12184
12630
  currentTask: {
12185
12631
  ...s.currentTask,
12186
- subtasks: updatedSubtasks
12632
+ subtasks: updatedSubtasks,
12633
+ currentSubtaskIndex: nextIndex < total ? nextIndex : currentIndex
12187
12634
  },
12188
12635
  lastUpdated: getTimestamp()
12189
12636
  }));
12190
- await this.publishEvent(projectId, "subtask.failed", {
12637
+ await this.publishEvent(projectId, "subtask.blocked", {
12191
12638
  taskId: state.currentTask.id,
12192
12639
  subtaskId: current.id,
12193
12640
  description: current.description,
12194
- error
12641
+ blocker
12195
12642
  });
12643
+ return nextIndex < total ? updatedSubtasks[nextIndex] : null;
12196
12644
  }
12197
12645
  };
12198
12646
  stateStorage = new StateStorage();
@@ -12200,7 +12648,7 @@ var init_state_storage = __esm({
12200
12648
  });
12201
12649
 
12202
12650
  // core/storage/storage.ts
12203
- import fs25 from "node:fs/promises";
12651
+ import fs26 from "node:fs/promises";
12204
12652
  import os8 from "node:os";
12205
12653
  import path24 from "node:path";
12206
12654
  function getStorage(projectId) {
@@ -12238,8 +12686,8 @@ var init_storage = __esm({
12238
12686
  }
12239
12687
  async write(pathArray, data) {
12240
12688
  const filePath = this.pathToFile(pathArray);
12241
- await fs25.mkdir(path24.dirname(filePath), { recursive: true });
12242
- await fs25.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
12689
+ await fs26.mkdir(path24.dirname(filePath), { recursive: true });
12690
+ await fs26.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
12243
12691
  eventBus.publish({
12244
12692
  type: inferEventType(pathArray, "write"),
12245
12693
  path: pathArray,
@@ -12254,7 +12702,7 @@ var init_storage = __esm({
12254
12702
  async read(pathArray) {
12255
12703
  const filePath = this.pathToFile(pathArray);
12256
12704
  try {
12257
- const content = await fs25.readFile(filePath, "utf-8");
12705
+ const content = await fs26.readFile(filePath, "utf-8");
12258
12706
  return JSON.parse(content);
12259
12707
  } catch (error) {
12260
12708
  if (isNotFoundError(error) || error instanceof SyntaxError) {
@@ -12266,7 +12714,7 @@ var init_storage = __esm({
12266
12714
  async list(prefix) {
12267
12715
  const dir = path24.join(this.basePath, `${prefix[0]}s`);
12268
12716
  try {
12269
- const files = await fs25.readdir(dir);
12717
+ const files = await fs26.readdir(dir);
12270
12718
  return files.filter((f) => f.endsWith(".json") && f !== "index.json").map((f) => [...prefix, f.replace(".json", "")]);
12271
12719
  } catch (error) {
12272
12720
  if (isNotFoundError(error)) {
@@ -12278,7 +12726,7 @@ var init_storage = __esm({
12278
12726
  async delete(pathArray) {
12279
12727
  const filePath = this.pathToFile(pathArray);
12280
12728
  try {
12281
- await fs25.unlink(filePath);
12729
+ await fs26.unlink(filePath);
12282
12730
  eventBus.publish({
12283
12731
  type: inferEventType(pathArray, "delete"),
12284
12732
  path: pathArray,
@@ -12298,7 +12746,7 @@ var init_storage = __esm({
12298
12746
  async exists(pathArray) {
12299
12747
  const filePath = this.pathToFile(pathArray);
12300
12748
  try {
12301
- await fs25.access(filePath);
12749
+ await fs26.access(filePath);
12302
12750
  return true;
12303
12751
  } catch (error) {
12304
12752
  if (isNotFoundError(error)) {
@@ -12314,7 +12762,7 @@ var init_storage = __esm({
12314
12762
  const indexPath = path24.join(this.basePath, `${collection}s`, "index.json");
12315
12763
  let index = { ids: [], updatedAt: "" };
12316
12764
  try {
12317
- const content = await fs25.readFile(indexPath, "utf-8");
12765
+ const content = await fs26.readFile(indexPath, "utf-8");
12318
12766
  index = JSON.parse(content);
12319
12767
  } catch (error) {
12320
12768
  if (!isNotFoundError(error) && !(error instanceof SyntaxError)) {
@@ -12327,8 +12775,8 @@ var init_storage = __esm({
12327
12775
  index.ids = index.ids.filter((i) => i !== id);
12328
12776
  }
12329
12777
  index.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
12330
- await fs25.mkdir(path24.dirname(indexPath), { recursive: true });
12331
- await fs25.writeFile(indexPath, JSON.stringify(index, null, 2), "utf-8");
12778
+ await fs26.mkdir(path24.dirname(indexPath), { recursive: true });
12779
+ await fs26.writeFile(indexPath, JSON.stringify(index, null, 2), "utf-8");
12332
12780
  }
12333
12781
  };
12334
12782
  __name(getStorage, "getStorage");
@@ -12351,7 +12799,7 @@ var init_storage2 = __esm({
12351
12799
  });
12352
12800
 
12353
12801
  // core/agentic/template-loader.ts
12354
- import fs26 from "node:fs/promises";
12802
+ import fs27 from "node:fs/promises";
12355
12803
  import path25 from "node:path";
12356
12804
  function updateLruOrder(key) {
12357
12805
  const index = cacheOrder.indexOf(key);
@@ -12392,7 +12840,7 @@ async function load(commandName) {
12392
12840
  }
12393
12841
  const templatePath = path25.join(TEMPLATES_DIR, `${commandName}.md`);
12394
12842
  try {
12395
- const rawContent = await fs26.readFile(templatePath, "utf-8");
12843
+ const rawContent = await fs27.readFile(templatePath, "utf-8");
12396
12844
  const parsed = parseFrontmatter(rawContent);
12397
12845
  evictLru();
12398
12846
  cache.set(commandName, parsed);
@@ -12432,7 +12880,7 @@ var init_template_loader = __esm({
12432
12880
 
12433
12881
  // core/agentic/orchestrator-executor.ts
12434
12882
  import { exec as execCallback5 } from "node:child_process";
12435
- import fs27 from "node:fs/promises";
12883
+ import fs28 from "node:fs/promises";
12436
12884
  import os9 from "node:os";
12437
12885
  import path26 from "node:path";
12438
12886
  import { promisify as promisify7 } from "node:util";
@@ -12703,7 +13151,7 @@ var init_orchestrator_executor = __esm({
12703
13151
  async loadRepoAnalysis(globalPath) {
12704
13152
  try {
12705
13153
  const analysisPath = path26.join(globalPath, "analysis", "repo-analysis.json");
12706
- const content = await fs27.readFile(analysisPath, "utf-8");
13154
+ const content = await fs28.readFile(analysisPath, "utf-8");
12707
13155
  return JSON.parse(content);
12708
13156
  } catch (error) {
12709
13157
  if (isNotFoundError(error)) return null;
@@ -12768,7 +13216,7 @@ var init_orchestrator_executor = __esm({
12768
13216
  async getAvailableAgentNames(globalPath) {
12769
13217
  try {
12770
13218
  const agentsDir = path26.join(globalPath, "agents");
12771
- const files = await fs27.readdir(agentsDir);
13219
+ const files = await fs28.readdir(agentsDir);
12772
13220
  return files.filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", ""));
12773
13221
  } catch {
12774
13222
  return [];
@@ -12790,7 +13238,7 @@ var init_orchestrator_executor = __esm({
12790
13238
  for (const fileName of possibleNames) {
12791
13239
  const filePath = path26.join(agentsDir, fileName);
12792
13240
  try {
12793
- const content = await fs27.readFile(filePath, "utf-8");
13241
+ const content = await fs28.readFile(filePath, "utf-8");
12794
13242
  const { frontmatter, body } = this.parseAgentFile(content);
12795
13243
  return {
12796
13244
  name: fileName.replace(".md", ""),
@@ -12845,11 +13293,11 @@ var init_orchestrator_executor = __esm({
12845
13293
  const flatPath = path26.join(skillsDir, `${skillName}.md`);
12846
13294
  const subdirPath = path26.join(skillsDir, skillName, "SKILL.md");
12847
13295
  try {
12848
- const content = await fs27.readFile(subdirPath, "utf-8");
13296
+ const content = await fs28.readFile(subdirPath, "utf-8");
12849
13297
  return { name: skillName, content, filePath: subdirPath };
12850
13298
  } catch {
12851
13299
  try {
12852
- const content = await fs27.readFile(flatPath, "utf-8");
13300
+ const content = await fs28.readFile(flatPath, "utf-8");
12853
13301
  return { name: skillName, content, filePath: flatPath };
12854
13302
  } catch {
12855
13303
  const agentNames = skillToAgents.get(skillName) || [];
@@ -13772,7 +14220,7 @@ var init_outcomes2 = __esm({
13772
14220
  });
13773
14221
 
13774
14222
  // core/agentic/prompt-builder.ts
13775
- import fs28 from "node:fs/promises";
14223
+ import fs29 from "node:fs/promises";
13776
14224
  import path28 from "node:path";
13777
14225
  var PromptBuilder, promptBuilder, prompt_builder_default;
13778
14226
  var init_prompt_builder = __esm({
@@ -13811,7 +14259,7 @@ var init_prompt_builder = __esm({
13811
14259
  }
13812
14260
  try {
13813
14261
  if (await fileExists(templatePath)) {
13814
- const content = await fs28.readFile(templatePath, "utf-8");
14262
+ const content = await fs29.readFile(templatePath, "utf-8");
13815
14263
  this._templateCache.set(templatePath, { content, loadedAt: now });
13816
14264
  return content;
13817
14265
  }
@@ -13882,7 +14330,7 @@ var init_prompt_builder = __esm({
13882
14330
  const checklists = {};
13883
14331
  try {
13884
14332
  if (await fileExists(checklistsDir)) {
13885
- const files = (await fs28.readdir(checklistsDir)).filter((f) => f.endsWith(".md"));
14333
+ const files = (await fs29.readdir(checklistsDir)).filter((f) => f.endsWith(".md"));
13886
14334
  for (const file of files) {
13887
14335
  const name = file.replace(".md", "");
13888
14336
  const templatePath = path28.join(checklistsDir, file);
@@ -14442,7 +14890,7 @@ Context: ${fileCount} files available. Read what you need.
14442
14890
  });
14443
14891
 
14444
14892
  // core/agentic/template-executor.ts
14445
- import fs29 from "node:fs/promises";
14893
+ import fs30 from "node:fs/promises";
14446
14894
  import path29 from "node:path";
14447
14895
  var ORCHESTRATED_COMMANDS, SIMPLE_COMMANDS, TemplateExecutor, templateExecutor, template_executor_default;
14448
14896
  var init_template_executor = __esm({
@@ -14521,7 +14969,7 @@ var init_template_executor = __esm({
14521
14969
  try {
14522
14970
  const projectId = await this.getProjectId(projectPath);
14523
14971
  const agentsDir = path29.join(path_manager_default.getGlobalProjectPath(projectId), "agents");
14524
- const files = await fs29.readdir(agentsDir);
14972
+ const files = await fs30.readdir(agentsDir);
14525
14973
  return files.some((f) => f.endsWith(".md"));
14526
14974
  } catch (error) {
14527
14975
  if (isNotFoundError(error)) return false;
@@ -14535,7 +14983,7 @@ var init_template_executor = __esm({
14535
14983
  try {
14536
14984
  const projectId = await this.getProjectId(projectPath);
14537
14985
  const agentsDir = path29.join(path_manager_default.getGlobalProjectPath(projectId), "agents");
14538
- const files = await fs29.readdir(agentsDir);
14986
+ const files = await fs30.readdir(agentsDir);
14539
14987
  return files.filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", ""));
14540
14988
  } catch {
14541
14989
  return [];
@@ -14644,7 +15092,7 @@ When fragmenting tasks:
14644
15092
 
14645
15093
  // core/agentic/tool-registry.ts
14646
15094
  import { exec as exec7 } from "node:child_process";
14647
- import fs30 from "node:fs/promises";
15095
+ import fs31 from "node:fs/promises";
14648
15096
  import { promisify as promisify8 } from "node:util";
14649
15097
  var execAsync4, toolRegistry, tool_registry_default;
14650
15098
  var init_tool_registry = __esm({
@@ -14688,14 +15136,14 @@ var init_tool_registry = __esm({
14688
15136
  };
14689
15137
  toolRegistry.register("Read", async (filePath) => {
14690
15138
  try {
14691
- return await fs30.readFile(filePath, "utf-8");
15139
+ return await fs31.readFile(filePath, "utf-8");
14692
15140
  } catch (_error) {
14693
15141
  return null;
14694
15142
  }
14695
15143
  });
14696
15144
  toolRegistry.register("Write", async (filePath, content) => {
14697
15145
  try {
14698
- await fs30.writeFile(filePath, content, "utf-8");
15146
+ await fs31.writeFile(filePath, content, "utf-8");
14699
15147
  return true;
14700
15148
  } catch (_error) {
14701
15149
  return false;
@@ -14730,23 +15178,23 @@ var init_tool_registry = __esm({
14730
15178
  });
14731
15179
 
14732
15180
  // core/agentic/command-executor.ts
14733
- import fs31 from "node:fs/promises";
15181
+ import fs32 from "node:fs/promises";
14734
15182
  import os10 from "node:os";
14735
15183
  import path30 from "node:path";
14736
15184
  async function signalStart(commandName) {
14737
15185
  try {
14738
15186
  const dir = path30.dirname(RUNNING_FILE);
14739
15187
  if (!await fileExists(dir)) {
14740
- await fs31.mkdir(dir, { recursive: true });
15188
+ await fs32.mkdir(dir, { recursive: true });
14741
15189
  }
14742
- await fs31.writeFile(RUNNING_FILE, `/p:${commandName}`);
15190
+ await fs32.writeFile(RUNNING_FILE, `/p:${commandName}`);
14743
15191
  } catch (_error) {
14744
15192
  }
14745
15193
  }
14746
15194
  async function signalEnd() {
14747
15195
  try {
14748
15196
  if (await fileExists(RUNNING_FILE)) {
14749
- await fs31.unlink(RUNNING_FILE);
15197
+ await fs32.unlink(RUNNING_FILE);
14750
15198
  }
14751
15199
  } catch (_error) {
14752
15200
  }
@@ -15079,7 +15527,7 @@ var init_command_executor = __esm({
15079
15527
  });
15080
15528
 
15081
15529
  // core/infrastructure/update-checker.ts
15082
- import fs32 from "node:fs/promises";
15530
+ import fs33 from "node:fs/promises";
15083
15531
  import https from "node:https";
15084
15532
  import os11 from "node:os";
15085
15533
  import path31 from "node:path";
@@ -15110,7 +15558,7 @@ var init_update_checker = __esm({
15110
15558
  async getCurrentVersion() {
15111
15559
  try {
15112
15560
  const packageJsonPath = path31.join(__dirname, "..", "..", "package.json");
15113
- const packageJson = JSON.parse(await fs32.readFile(packageJsonPath, "utf8"));
15561
+ const packageJson = JSON.parse(await fs33.readFile(packageJsonPath, "utf8"));
15114
15562
  return packageJson.version;
15115
15563
  } catch (error) {
15116
15564
  console.error("Error reading package version:", getErrorMessage2(error));
@@ -15180,7 +15628,7 @@ var init_update_checker = __esm({
15180
15628
  async readCache() {
15181
15629
  try {
15182
15630
  if (await fileExists(this.cacheFile)) {
15183
- const cache2 = JSON.parse(await fs32.readFile(this.cacheFile, "utf8"));
15631
+ const cache2 = JSON.parse(await fs33.readFile(this.cacheFile, "utf8"));
15184
15632
  return cache2;
15185
15633
  }
15186
15634
  } catch (_error) {
@@ -15193,9 +15641,9 @@ var init_update_checker = __esm({
15193
15641
  async writeCache(data) {
15194
15642
  try {
15195
15643
  if (!await fileExists(this.cacheDir)) {
15196
- await fs32.mkdir(this.cacheDir, { recursive: true });
15644
+ await fs33.mkdir(this.cacheDir, { recursive: true });
15197
15645
  }
15198
- await fs32.writeFile(this.cacheFile, JSON.stringify(data, null, 2), "utf8");
15646
+ await fs33.writeFile(this.cacheFile, JSON.stringify(data, null, 2), "utf8");
15199
15647
  } catch (_error) {
15200
15648
  }
15201
15649
  }
@@ -15353,7 +15801,7 @@ var init_agent_generator = __esm({
15353
15801
  });
15354
15802
 
15355
15803
  // core/agentic/agent-router.ts
15356
- import fs33 from "node:fs/promises";
15804
+ import fs34 from "node:fs/promises";
15357
15805
  import path32 from "node:path";
15358
15806
  var AgentRouter, agent_router_default;
15359
15807
  var init_agent_router = __esm({
@@ -15383,12 +15831,12 @@ var init_agent_router = __esm({
15383
15831
  async loadAvailableAgents() {
15384
15832
  if (!this.agentsPath) return [];
15385
15833
  try {
15386
- const files = await fs33.readdir(this.agentsPath);
15834
+ const files = await fs34.readdir(this.agentsPath);
15387
15835
  const agents = [];
15388
15836
  for (const file of files) {
15389
15837
  if (file.endsWith(".md")) {
15390
15838
  const name = file.replace(".md", "");
15391
- const content = await fs33.readFile(path32.join(this.agentsPath, file), "utf-8");
15839
+ const content = await fs34.readFile(path32.join(this.agentsPath, file), "utf-8");
15392
15840
  agents.push({ name, content });
15393
15841
  }
15394
15842
  }
@@ -15414,7 +15862,7 @@ var init_agent_router = __esm({
15414
15862
  if (!this.agentsPath) return null;
15415
15863
  try {
15416
15864
  const filePath = path32.join(this.agentsPath, `${name}.md`);
15417
- const content = await fs33.readFile(filePath, "utf-8");
15865
+ const content = await fs34.readFile(filePath, "utf-8");
15418
15866
  return { name, content };
15419
15867
  } catch (error) {
15420
15868
  if (!isNotFoundError(error)) {
@@ -15456,7 +15904,7 @@ var init_agent_router = __esm({
15456
15904
  projectId: this.projectId
15457
15905
  })}
15458
15906
  `;
15459
- await fs33.appendFile(logPath, entry);
15907
+ await fs34.appendFile(logPath, entry);
15460
15908
  } catch (error) {
15461
15909
  if (!isNotFoundError(error)) {
15462
15910
  console.error(`Agent usage log error: ${getErrorMessage2(error)}`);
@@ -16935,7 +17383,7 @@ var init_memory_service = __esm({
16935
17383
  });
16936
17384
 
16937
17385
  // core/services/nested-context-resolver.ts
16938
- import fs34 from "node:fs/promises";
17386
+ import fs35 from "node:fs/promises";
16939
17387
  import path36 from "node:path";
16940
17388
  var NestedContextResolver;
16941
17389
  var init_nested_context_resolver = __esm({
@@ -16989,7 +17437,7 @@ var init_nested_context_resolver = __esm({
16989
17437
  * Load a single PRJCT.md file into a NestedContext
16990
17438
  */
16991
17439
  async loadContext(filePath, parent, pkg = null) {
16992
- const content = await fs34.readFile(filePath, "utf-8");
17440
+ const content = await fs35.readFile(filePath, "utf-8");
16993
17441
  const relativePath = path36.relative(this.rootPath, filePath);
16994
17442
  const depth = relativePath.split(path36.sep).length - 1;
16995
17443
  return {
@@ -17045,7 +17493,7 @@ var init_nested_context_resolver = __esm({
17045
17493
  const scan = /* @__PURE__ */ __name(async (currentDir, depth) => {
17046
17494
  if (depth > 5) return;
17047
17495
  try {
17048
- const entries = await fs34.readdir(currentDir, { withFileTypes: true });
17496
+ const entries = await fs35.readdir(currentDir, { withFileTypes: true });
17049
17497
  for (const entry of entries) {
17050
17498
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "coverage") {
17051
17499
  continue;
@@ -17212,7 +17660,7 @@ ${content}`);
17212
17660
  * Load a single AGENTS.md file into a NestedAgents structure
17213
17661
  */
17214
17662
  async loadAgents(filePath, parent, pkg = null) {
17215
- const content = await fs34.readFile(filePath, "utf-8");
17663
+ const content = await fs35.readFile(filePath, "utf-8");
17216
17664
  const relativePath = path36.relative(this.rootPath, filePath);
17217
17665
  const depth = relativePath.split(path36.sep).length - 1;
17218
17666
  return {
@@ -17347,7 +17795,7 @@ ${content}`);
17347
17795
  const scan = /* @__PURE__ */ __name(async (currentDir, depth) => {
17348
17796
  if (depth > 5) return;
17349
17797
  try {
17350
- const entries = await fs34.readdir(currentDir, { withFileTypes: true });
17798
+ const entries = await fs35.readdir(currentDir, { withFileTypes: true });
17351
17799
  for (const entry of entries) {
17352
17800
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "coverage") {
17353
17801
  continue;
@@ -17511,150 +17959,6 @@ var init_project_index = __esm({
17511
17959
  }
17512
17960
  });
17513
17961
 
17514
- // core/workflow/state-machine.ts
17515
- var WORKFLOW_STATES, WorkflowStateMachine, workflowStateMachine;
17516
- var init_state_machine = __esm({
17517
- "core/workflow/state-machine.ts"() {
17518
- "use strict";
17519
- WORKFLOW_STATES = {
17520
- idle: {
17521
- transitions: ["task", "next"],
17522
- prompt: "p. task <description> Start working",
17523
- description: "No active task"
17524
- },
17525
- working: {
17526
- transitions: ["done", "pause"],
17527
- prompt: "p. done Complete task | p. pause Switch context",
17528
- description: "Task in progress"
17529
- },
17530
- paused: {
17531
- transitions: ["resume", "task"],
17532
- prompt: "p. resume Continue | p. task <new> Start different",
17533
- description: "Task paused"
17534
- },
17535
- completed: {
17536
- transitions: ["ship", "task", "next"],
17537
- prompt: "p. ship Ship it | p. task <next> Start next",
17538
- description: "Task completed"
17539
- },
17540
- shipped: {
17541
- transitions: ["task", "next"],
17542
- prompt: "p. task <description> Start new task",
17543
- description: "Feature shipped"
17544
- }
17545
- };
17546
- WorkflowStateMachine = class {
17547
- static {
17548
- __name(this, "WorkflowStateMachine");
17549
- }
17550
- /**
17551
- * Get current state from storage state
17552
- */
17553
- getCurrentState(storageState) {
17554
- const task = storageState?.currentTask;
17555
- if (!task) {
17556
- return "idle";
17557
- }
17558
- const status = task.status?.toLowerCase();
17559
- switch (status) {
17560
- case "in_progress":
17561
- case "working":
17562
- return "working";
17563
- case "paused":
17564
- return "paused";
17565
- case "completed":
17566
- case "done":
17567
- return "completed";
17568
- case "shipped":
17569
- return "shipped";
17570
- default:
17571
- return task ? "working" : "idle";
17572
- }
17573
- }
17574
- /**
17575
- * Check if a command is valid for the current state
17576
- */
17577
- canTransition(currentState, command) {
17578
- const stateConfig = WORKFLOW_STATES[currentState];
17579
- if (stateConfig.transitions.includes(command)) {
17580
- return { valid: true };
17581
- }
17582
- const validCommands = stateConfig.transitions.map((c) => `p. ${c}`).join(", ");
17583
- return {
17584
- valid: false,
17585
- error: `Cannot run 'p. ${command}' in ${currentState} state`,
17586
- suggestion: `Valid commands: ${validCommands}`
17587
- };
17588
- }
17589
- /**
17590
- * Get the next state after a command
17591
- */
17592
- getNextState(currentState, command) {
17593
- switch (command) {
17594
- case "task":
17595
- return "working";
17596
- case "done":
17597
- return "completed";
17598
- case "pause":
17599
- return "paused";
17600
- case "resume":
17601
- return "working";
17602
- case "ship":
17603
- return "shipped";
17604
- case "next":
17605
- return currentState;
17606
- // next doesn't change state
17607
- default:
17608
- return currentState;
17609
- }
17610
- }
17611
- /**
17612
- * Get state definition
17613
- */
17614
- getStateInfo(state) {
17615
- return WORKFLOW_STATES[state];
17616
- }
17617
- /**
17618
- * Get prompt for current state
17619
- */
17620
- getPrompt(state) {
17621
- return WORKFLOW_STATES[state].prompt;
17622
- }
17623
- /**
17624
- * Get valid commands for current state
17625
- */
17626
- getValidCommands(state) {
17627
- return WORKFLOW_STATES[state].transitions;
17628
- }
17629
- /**
17630
- * Format next steps for display
17631
- */
17632
- formatNextSteps(state) {
17633
- const stateConfig = WORKFLOW_STATES[state];
17634
- return stateConfig.transitions.map((cmd) => {
17635
- switch (cmd) {
17636
- case "task":
17637
- return "p. task <desc> Start new task";
17638
- case "done":
17639
- return "p. done Complete current task";
17640
- case "pause":
17641
- return "p. pause Pause and switch context";
17642
- case "resume":
17643
- return "p. resume Continue paused task";
17644
- case "ship":
17645
- return "p. ship Ship the feature";
17646
- case "next":
17647
- return "p. next View task queue";
17648
- default:
17649
- return `p. ${cmd}`;
17650
- }
17651
- });
17652
- }
17653
- };
17654
- workflowStateMachine = new WorkflowStateMachine();
17655
- }
17656
- });
17657
-
17658
17962
  // core/utils/next-steps.ts
17659
17963
  import chalk9 from "chalk";
17660
17964
  function showNextSteps(command, options = {}) {
@@ -17687,6 +17991,7 @@ var init_next_steps = __esm({
17687
17991
  pause: "Pause and switch context",
17688
17992
  resume: "Continue paused task",
17689
17993
  ship: "Ship the feature",
17994
+ reopen: "Reopen for rework",
17690
17995
  next: "View task queue",
17691
17996
  sync: "Analyze project",
17692
17997
  bug: "Report a bug",
@@ -17700,6 +18005,7 @@ var init_next_steps = __esm({
17700
18005
  pause: "paused",
17701
18006
  resume: "working",
17702
18007
  ship: "shipped",
18008
+ reopen: "working",
17703
18009
  next: "idle",
17704
18010
  sync: "idle",
17705
18011
  init: "idle",
@@ -17980,16 +18286,16 @@ var init_onboarding = __esm({
17980
18286
  * Detect project type from file system
17981
18287
  */
17982
18288
  async detectProjectType() {
17983
- const fs52 = await import("node:fs/promises");
18289
+ const fs53 = await import("node:fs/promises");
17984
18290
  const path65 = await import("node:path");
17985
18291
  try {
17986
- const files = await fs52.readdir(this.projectPath);
18292
+ const files = await fs53.readdir(this.projectPath);
17987
18293
  if (files.includes("turbo.json") || files.includes("lerna.json") || files.includes("nx.json")) {
17988
18294
  return "monorepo";
17989
18295
  }
17990
18296
  if (files.includes("package.json")) {
17991
18297
  const pkgPath = path65.join(this.projectPath, "package.json");
17992
- const pkgContent = await fs52.readFile(pkgPath, "utf-8");
18298
+ const pkgContent = await fs53.readFile(pkgPath, "utf-8");
17993
18299
  const pkg = JSON.parse(pkgContent);
17994
18300
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
17995
18301
  if (pkg.bin) return "cli-tool";
@@ -18025,32 +18331,32 @@ var init_onboarding = __esm({
18025
18331
  * Detect installed AI agents from config files
18026
18332
  */
18027
18333
  async detectInstalledAgents() {
18028
- const fs52 = await import("node:fs/promises");
18334
+ const fs53 = await import("node:fs/promises");
18029
18335
  const path65 = await import("node:path");
18030
18336
  const os21 = await import("node:os");
18031
18337
  const agents = [];
18032
18338
  try {
18033
- await fs52.access(path65.join(os21.homedir(), ".claude"));
18339
+ await fs53.access(path65.join(os21.homedir(), ".claude"));
18034
18340
  agents.push("claude");
18035
18341
  } catch {
18036
18342
  }
18037
18343
  try {
18038
- await fs52.access(path65.join(this.projectPath, ".cursorrules"));
18344
+ await fs53.access(path65.join(this.projectPath, ".cursorrules"));
18039
18345
  agents.push("cursor");
18040
18346
  } catch {
18041
18347
  }
18042
18348
  try {
18043
- await fs52.access(path65.join(this.projectPath, ".windsurfrules"));
18349
+ await fs53.access(path65.join(this.projectPath, ".windsurfrules"));
18044
18350
  agents.push("windsurf");
18045
18351
  } catch {
18046
18352
  }
18047
18353
  try {
18048
- await fs52.access(path65.join(this.projectPath, ".github", "copilot-instructions.md"));
18354
+ await fs53.access(path65.join(this.projectPath, ".github", "copilot-instructions.md"));
18049
18355
  agents.push("copilot");
18050
18356
  } catch {
18051
18357
  }
18052
18358
  try {
18053
- await fs52.access(path65.join(os21.homedir(), ".gemini"));
18359
+ await fs53.access(path65.join(os21.homedir(), ".gemini"));
18054
18360
  agents.push("gemini");
18055
18361
  } catch {
18056
18362
  }
@@ -18060,17 +18366,17 @@ var init_onboarding = __esm({
18060
18366
  * Detect tech stack from project files
18061
18367
  */
18062
18368
  async detectStack() {
18063
- const fs52 = await import("node:fs/promises");
18369
+ const fs53 = await import("node:fs/promises");
18064
18370
  const path65 = await import("node:path");
18065
18371
  const stack = {
18066
18372
  language: "Unknown",
18067
18373
  technologies: []
18068
18374
  };
18069
18375
  try {
18070
- const files = await fs52.readdir(this.projectPath);
18376
+ const files = await fs53.readdir(this.projectPath);
18071
18377
  if (files.includes("package.json")) {
18072
18378
  const pkgPath = path65.join(this.projectPath, "package.json");
18073
- const pkgContent = await fs52.readFile(pkgPath, "utf-8");
18379
+ const pkgContent = await fs53.readFile(pkgPath, "utf-8");
18074
18380
  const pkg = JSON.parse(pkgContent);
18075
18381
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
18076
18382
  stack.language = deps.typescript ? "TypeScript" : "JavaScript";
@@ -18177,14 +18483,14 @@ var init_wizard = __esm({
18177
18483
 
18178
18484
  // core/context/generator.ts
18179
18485
  import { exec as exec10 } from "node:child_process";
18180
- import fs35 from "node:fs/promises";
18486
+ import fs36 from "node:fs/promises";
18181
18487
  import path37 from "node:path";
18182
18488
  import { promisify as promisify11 } from "node:util";
18183
18489
  async function generateContext(projectId, repoPath) {
18184
18490
  const _globalPath = path_manager_default.getGlobalProjectPath(projectId);
18185
18491
  const contextPath = path_manager_default.getContextPath(projectId);
18186
18492
  const storage = getStorage(projectId);
18187
- await fs35.mkdir(contextPath, { recursive: true });
18493
+ await fs36.mkdir(contextPath, { recursive: true });
18188
18494
  const project = await storage.read(["project"]) || {};
18189
18495
  const taskPaths = await storage.list(["task"]);
18190
18496
  const featurePaths = await storage.list(["feature"]);
@@ -18267,7 +18573,7 @@ async function getPackageData(repoPath) {
18267
18573
  };
18268
18574
  try {
18269
18575
  const pkgPath = path37.join(repoPath, "package.json");
18270
- const pkg = JSON.parse(await fs35.readFile(pkgPath, "utf-8"));
18576
+ const pkg = JSON.parse(await fs36.readFile(pkgPath, "utf-8"));
18271
18577
  data.dependencies = pkg.dependencies || {};
18272
18578
  data.devDependencies = pkg.devDependencies || {};
18273
18579
  data.scripts = pkg.scripts || {};
@@ -18351,7 +18657,7 @@ ${agents.length > 0 ? agents.map((a) => `- **${a.name}**: ${a.role || "Specialis
18351
18657
  \u2514\u2500\u2500 pending.json
18352
18658
  \`\`\`
18353
18659
  `;
18354
- await fs35.writeFile(path37.join(contextPath, "CLAUDE.md"), content, "utf-8");
18660
+ await fs36.writeFile(path37.join(contextPath, "CLAUDE.md"), content, "utf-8");
18355
18661
  }
18356
18662
  async function generateNowMd(contextPath, tasks) {
18357
18663
  const currentTask = tasks.find((t) => t.status === "in_progress");
@@ -18366,7 +18672,7 @@ async function generateNowMd(contextPath, tasks) {
18366
18672
 
18367
18673
  _No active task. Use /p:now to start._
18368
18674
  `;
18369
- await fs35.writeFile(path37.join(contextPath, "now.md"), content, "utf-8");
18675
+ await fs36.writeFile(path37.join(contextPath, "now.md"), content, "utf-8");
18370
18676
  }
18371
18677
  async function generateQueueMd(contextPath, tasks) {
18372
18678
  const pendingTasks = tasks.filter((t) => t.status === "pending");
@@ -18374,7 +18680,7 @@ async function generateQueueMd(contextPath, tasks) {
18374
18680
 
18375
18681
  ${pendingTasks.length > 0 ? pendingTasks.map((t, i) => `${i + 1}. ${t.description}${t.priority ? ` [${t.priority}]` : ""}`).join("\n") : "_Empty queue. Use /p:next to add tasks._"}
18376
18682
  `;
18377
- await fs35.writeFile(path37.join(contextPath, "queue.md"), content, "utf-8");
18683
+ await fs36.writeFile(path37.join(contextPath, "queue.md"), content, "utf-8");
18378
18684
  }
18379
18685
  async function generateSummaryMd(contextPath, project, gitData, pkgData) {
18380
18686
  const content = `# PROJECT SUMMARY
@@ -18394,7 +18700,7 @@ async function generateSummaryMd(contextPath, project, gitData, pkgData) {
18394
18700
  - Production: ${Object.keys(pkgData.dependencies).length}
18395
18701
  - Dev: ${Object.keys(pkgData.devDependencies).length}
18396
18702
  `;
18397
- await fs35.writeFile(path37.join(contextPath, "summary.md"), content, "utf-8");
18703
+ await fs36.writeFile(path37.join(contextPath, "summary.md"), content, "utf-8");
18398
18704
  }
18399
18705
  var execAsync7;
18400
18706
  var init_generator = __esm({
@@ -18415,7 +18721,7 @@ var init_generator = __esm({
18415
18721
 
18416
18722
  // core/domain/analyzer.ts
18417
18723
  import { exec as execCallback6 } from "node:child_process";
18418
- import fs36 from "node:fs/promises";
18724
+ import fs37 from "node:fs/promises";
18419
18725
  import path38 from "node:path";
18420
18726
  import { promisify as promisify12 } from "node:util";
18421
18727
  var exec11, CodebaseAnalyzer, analyzer, analyzer_default2;
@@ -18441,7 +18747,7 @@ var init_analyzer2 = __esm({
18441
18747
  async readPackageJson() {
18442
18748
  try {
18443
18749
  const packagePath = path38.join(this.projectPath, "package.json");
18444
- const content = await fs36.readFile(packagePath, "utf-8");
18750
+ const content = await fs37.readFile(packagePath, "utf-8");
18445
18751
  return JSON.parse(content);
18446
18752
  } catch (error) {
18447
18753
  if (isNotFoundError(error) || error instanceof SyntaxError) {
@@ -18456,7 +18762,7 @@ var init_analyzer2 = __esm({
18456
18762
  async readCargoToml() {
18457
18763
  try {
18458
18764
  const cargoPath = path38.join(this.projectPath, "Cargo.toml");
18459
- return await fs36.readFile(cargoPath, "utf-8");
18765
+ return await fs37.readFile(cargoPath, "utf-8");
18460
18766
  } catch (error) {
18461
18767
  if (isNotFoundError(error)) {
18462
18768
  return null;
@@ -18470,7 +18776,7 @@ var init_analyzer2 = __esm({
18470
18776
  async readRequirements() {
18471
18777
  try {
18472
18778
  const reqPath = path38.join(this.projectPath, "requirements.txt");
18473
- return await fs36.readFile(reqPath, "utf-8");
18779
+ return await fs37.readFile(reqPath, "utf-8");
18474
18780
  } catch (error) {
18475
18781
  if (isNotFoundError(error)) {
18476
18782
  return null;
@@ -18484,7 +18790,7 @@ var init_analyzer2 = __esm({
18484
18790
  async readGoMod() {
18485
18791
  try {
18486
18792
  const goModPath = path38.join(this.projectPath, "go.mod");
18487
- return await fs36.readFile(goModPath, "utf-8");
18793
+ return await fs37.readFile(goModPath, "utf-8");
18488
18794
  } catch (error) {
18489
18795
  if (isNotFoundError(error)) {
18490
18796
  return null;
@@ -18498,7 +18804,7 @@ var init_analyzer2 = __esm({
18498
18804
  async readGemfile() {
18499
18805
  try {
18500
18806
  const gemfilePath = path38.join(this.projectPath, "Gemfile");
18501
- return await fs36.readFile(gemfilePath, "utf-8");
18807
+ return await fs37.readFile(gemfilePath, "utf-8");
18502
18808
  } catch (error) {
18503
18809
  if (isNotFoundError(error)) {
18504
18810
  return null;
@@ -18512,7 +18818,7 @@ var init_analyzer2 = __esm({
18512
18818
  async readMixExs() {
18513
18819
  try {
18514
18820
  const mixPath = path38.join(this.projectPath, "mix.exs");
18515
- return await fs36.readFile(mixPath, "utf-8");
18821
+ return await fs37.readFile(mixPath, "utf-8");
18516
18822
  } catch (error) {
18517
18823
  if (isNotFoundError(error)) {
18518
18824
  return null;
@@ -18526,7 +18832,7 @@ var init_analyzer2 = __esm({
18526
18832
  async readPomXml() {
18527
18833
  try {
18528
18834
  const pomPath = path38.join(this.projectPath, "pom.xml");
18529
- return await fs36.readFile(pomPath, "utf-8");
18835
+ return await fs37.readFile(pomPath, "utf-8");
18530
18836
  } catch (error) {
18531
18837
  if (isNotFoundError(error)) {
18532
18838
  return null;
@@ -18540,7 +18846,7 @@ var init_analyzer2 = __esm({
18540
18846
  async readComposerJson() {
18541
18847
  try {
18542
18848
  const composerPath = path38.join(this.projectPath, "composer.json");
18543
- const content = await fs36.readFile(composerPath, "utf-8");
18849
+ const content = await fs37.readFile(composerPath, "utf-8");
18544
18850
  return JSON.parse(content);
18545
18851
  } catch (error) {
18546
18852
  if (isNotFoundError(error) || error instanceof SyntaxError) {
@@ -18555,7 +18861,7 @@ var init_analyzer2 = __esm({
18555
18861
  async readPyprojectToml() {
18556
18862
  try {
18557
18863
  const pyprojectPath = path38.join(this.projectPath, "pyproject.toml");
18558
- return await fs36.readFile(pyprojectPath, "utf-8");
18864
+ return await fs37.readFile(pyprojectPath, "utf-8");
18559
18865
  } catch (error) {
18560
18866
  if (isNotFoundError(error)) {
18561
18867
  return null;
@@ -18591,7 +18897,7 @@ var init_analyzer2 = __esm({
18591
18897
  */
18592
18898
  async listConfigFiles() {
18593
18899
  try {
18594
- const entries = await fs36.readdir(this.projectPath);
18900
+ const entries = await fs37.readdir(this.projectPath);
18595
18901
  const configPatterns = [
18596
18902
  /^package\.json$/,
18597
18903
  /^Cargo\.toml$/,
@@ -18621,7 +18927,7 @@ var init_analyzer2 = __esm({
18621
18927
  */
18622
18928
  async listDirectories() {
18623
18929
  try {
18624
- const entries = await fs36.readdir(this.projectPath, { withFileTypes: true });
18930
+ const entries = await fs37.readdir(this.projectPath, { withFileTypes: true });
18625
18931
  return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => !name.startsWith(".") && name !== "node_modules");
18626
18932
  } catch (error) {
18627
18933
  if (isNotFoundError(error)) {
@@ -18692,7 +18998,7 @@ var init_analyzer2 = __esm({
18692
18998
  */
18693
18999
  async fileExists(filename) {
18694
19000
  try {
18695
- await fs36.access(path38.join(this.projectPath, filename));
19001
+ await fs37.access(path38.join(this.projectPath, filename));
18696
19002
  return true;
18697
19003
  } catch (error) {
18698
19004
  if (isNotFoundError(error)) {
@@ -18707,7 +19013,7 @@ var init_analyzer2 = __esm({
18707
19013
  async readFile(relativePath) {
18708
19014
  try {
18709
19015
  const fullPath = path38.join(this.projectPath, relativePath);
18710
- return await fs36.readFile(fullPath, "utf-8");
19016
+ return await fs37.readFile(fullPath, "utf-8");
18711
19017
  } catch (error) {
18712
19018
  if (isNotFoundError(error)) {
18713
19019
  return null;
@@ -18955,7 +19261,7 @@ var analysis_exports = {};
18955
19261
  __export(analysis_exports, {
18956
19262
  AnalysisCommands: () => AnalysisCommands
18957
19263
  });
18958
- import fs37 from "node:fs/promises";
19264
+ import fs38 from "node:fs/promises";
18959
19265
  import path39 from "node:path";
18960
19266
  import prompts2 from "prompts";
18961
19267
  var AnalysisCommands;
@@ -19187,7 +19493,7 @@ var init_analysis2 = __esm({
19187
19493
  const claudeMdPath = path39.join(globalPath, "context", "CLAUDE.md");
19188
19494
  let existingContent = null;
19189
19495
  try {
19190
- existingContent = await fs37.readFile(claudeMdPath, "utf-8");
19496
+ existingContent = await fs38.readFile(claudeMdPath, "utf-8");
19191
19497
  } catch {
19192
19498
  }
19193
19499
  const isNonInteractive = !process.stdin.isTTY || options.json;
@@ -19206,7 +19512,7 @@ var init_analysis2 = __esm({
19206
19512
  }
19207
19513
  let newContent;
19208
19514
  try {
19209
- newContent = await fs37.readFile(claudeMdPath, "utf-8");
19515
+ newContent = await fs38.readFile(claudeMdPath, "utf-8");
19210
19516
  } catch {
19211
19517
  newContent = "";
19212
19518
  }
@@ -19230,7 +19536,7 @@ var init_analysis2 = __esm({
19230
19536
  }
19231
19537
  const restoreOriginal = /* @__PURE__ */ __name(async () => {
19232
19538
  if (existingContent != null) {
19233
- await fs37.writeFile(claudeMdPath, existingContent, "utf-8");
19539
+ await fs38.writeFile(claudeMdPath, existingContent, "utf-8");
19234
19540
  }
19235
19541
  }, "restoreOriginal");
19236
19542
  if (isNonInteractive) {
@@ -19449,7 +19755,7 @@ ${formatFullDiff(diff)}`);
19449
19755
  let projectName = "Unknown";
19450
19756
  try {
19451
19757
  const projectJson = JSON.parse(
19452
- await fs37.readFile(path39.join(globalPath, "project.json"), "utf-8")
19758
+ await fs38.readFile(path39.join(globalPath, "project.json"), "utf-8")
19453
19759
  );
19454
19760
  projectName = projectJson.name || "Unknown";
19455
19761
  } catch {
@@ -20204,8 +20510,8 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
20204
20510
  const globalPath2 = path_manager_default.getGlobalProjectPath(projectId);
20205
20511
  const specsPath2 = path40.join(globalPath2, "planning", "specs");
20206
20512
  try {
20207
- const fs52 = await import("node:fs/promises");
20208
- const files = await fs52.readdir(specsPath2);
20513
+ const fs53 = await import("node:fs/promises");
20514
+ const files = await fs53.readdir(specsPath2);
20209
20515
  const specs = files.filter((f) => f.endsWith(".md") && f !== ".gitkeep");
20210
20516
  if (specs.length === 0) {
20211
20517
  output_default.warn("no specs yet");
@@ -20419,7 +20725,7 @@ var init_project_service = __esm({
20419
20725
 
20420
20726
  // core/services/staleness-checker.ts
20421
20727
  import { exec as exec12 } from "node:child_process";
20422
- import fs38 from "node:fs/promises";
20728
+ import fs39 from "node:fs/promises";
20423
20729
  import path41 from "node:path";
20424
20730
  import { promisify as promisify13 } from "node:util";
20425
20731
  var execAsync8, DEFAULT_CONFIG, StalenessChecker, createStalenessChecker;
@@ -20473,7 +20779,7 @@ var init_staleness_checker = __esm({
20473
20779
  const projectJsonPath = path41.join(path_manager_default.getGlobalProjectPath(projectId), "project.json");
20474
20780
  let projectJson = {};
20475
20781
  try {
20476
- projectJson = JSON.parse(await fs38.readFile(projectJsonPath, "utf-8"));
20782
+ projectJson = JSON.parse(await fs39.readFile(projectJsonPath, "utf-8"));
20477
20783
  } catch {
20478
20784
  status.isStale = true;
20479
20785
  status.reason = "No sync history found. Run `prjct sync` to initialize.";
@@ -21040,7 +21346,7 @@ var init_registry = __esm({
21040
21346
  });
21041
21347
 
21042
21348
  // core/ai-tools/generator.ts
21043
- import fs39 from "node:fs/promises";
21349
+ import fs40 from "node:fs/promises";
21044
21350
  import path43 from "node:path";
21045
21351
  async function generateAIToolContexts(context2, globalPath, repoPath, toolIds = DEFAULT_AI_TOOLS) {
21046
21352
  const results = [];
@@ -21080,9 +21386,9 @@ async function generateForTool(context2, config, globalPath, repoPath) {
21080
21386
  } else {
21081
21387
  outputPath = path43.join(globalPath, "context", config.outputFile);
21082
21388
  }
21083
- await fs39.mkdir(path43.dirname(outputPath), { recursive: true });
21389
+ await fs40.mkdir(path43.dirname(outputPath), { recursive: true });
21084
21390
  try {
21085
- const existingContent = await fs39.readFile(outputPath, "utf-8");
21391
+ const existingContent = await fs40.readFile(outputPath, "utf-8");
21086
21392
  const validation = validatePreserveBlocks(existingContent);
21087
21393
  if (!validation.valid) {
21088
21394
  console.warn(`\u26A0\uFE0F ${config.outputFile} has invalid preserve blocks:`);
@@ -21093,7 +21399,7 @@ async function generateForTool(context2, config, globalPath, repoPath) {
21093
21399
  content = mergePreservedSections(content, existingContent);
21094
21400
  } catch {
21095
21401
  }
21096
- await fs39.writeFile(outputPath, content, "utf-8");
21402
+ await fs40.writeFile(outputPath, content, "utf-8");
21097
21403
  return {
21098
21404
  toolId: config.id,
21099
21405
  outputFile: config.outputFile,
@@ -21133,7 +21439,7 @@ var init_ai_tools = __esm({
21133
21439
  });
21134
21440
 
21135
21441
  // core/services/context-generator.ts
21136
- import fs40 from "node:fs/promises";
21442
+ import fs41 from "node:fs/promises";
21137
21443
  import path44 from "node:path";
21138
21444
  var ContextFileGenerator;
21139
21445
  var init_context_generator = __esm({
@@ -21159,7 +21465,7 @@ var init_context_generator = __esm({
21159
21465
  async writeWithPreservation(filePath, content) {
21160
21466
  let finalContent = content;
21161
21467
  try {
21162
- const existingContent = await fs40.readFile(filePath, "utf-8");
21468
+ const existingContent = await fs41.readFile(filePath, "utf-8");
21163
21469
  const validation = validatePreserveBlocks(existingContent);
21164
21470
  if (!validation.valid) {
21165
21471
  const filename = path44.basename(filePath);
@@ -21171,7 +21477,7 @@ var init_context_generator = __esm({
21171
21477
  finalContent = mergePreservedSections(content, existingContent);
21172
21478
  } catch {
21173
21479
  }
21174
- await fs40.writeFile(filePath, finalContent, "utf-8");
21480
+ await fs41.writeFile(filePath, finalContent, "utf-8");
21175
21481
  }
21176
21482
  /**
21177
21483
  * Generate all context files in parallel
@@ -21287,7 +21593,7 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
21287
21593
  let currentTask = null;
21288
21594
  try {
21289
21595
  const statePath = path44.join(this.config.globalPath, "storage", "state.json");
21290
- const state = JSON.parse(await fs40.readFile(statePath, "utf-8"));
21596
+ const state = JSON.parse(await fs41.readFile(statePath, "utf-8"));
21291
21597
  currentTask = state.currentTask;
21292
21598
  } catch {
21293
21599
  }
@@ -21312,7 +21618,7 @@ Use \`p. task "description"\` to start working.
21312
21618
  let queue = { tasks: [] };
21313
21619
  try {
21314
21620
  const queuePath = path44.join(this.config.globalPath, "storage", "queue.json");
21315
- queue = JSON.parse(await fs40.readFile(queuePath, "utf-8"));
21621
+ queue = JSON.parse(await fs41.readFile(queuePath, "utf-8"));
21316
21622
  } catch {
21317
21623
  }
21318
21624
  const content = `# NEXT
@@ -21328,7 +21634,7 @@ ${queue.tasks.length > 0 ? queue.tasks.map((t, i) => `${i + 1}. ${t.description}
21328
21634
  let ideas = { ideas: [] };
21329
21635
  try {
21330
21636
  const ideasPath = path44.join(this.config.globalPath, "storage", "ideas.json");
21331
- ideas = JSON.parse(await fs40.readFile(ideasPath, "utf-8"));
21637
+ ideas = JSON.parse(await fs41.readFile(ideasPath, "utf-8"));
21332
21638
  } catch {
21333
21639
  }
21334
21640
  const content = `# IDEAS
@@ -21346,7 +21652,7 @@ ${ideas.ideas.length > 0 ? ideas.ideas.map((i) => `- ${i.text}${i.priority ? ` [
21346
21652
  };
21347
21653
  try {
21348
21654
  const shippedPath = path44.join(this.config.globalPath, "storage", "shipped.json");
21349
- shipped = JSON.parse(await fs40.readFile(shippedPath, "utf-8"));
21655
+ shipped = JSON.parse(await fs41.readFile(shippedPath, "utf-8"));
21350
21656
  } catch {
21351
21657
  }
21352
21658
  const content = `# SHIPPED \u{1F680}
@@ -21400,7 +21706,7 @@ ${shipped.shipped.length > 0 ? shipped.shipped.slice(-10).map((s) => `- **${s.na
21400
21706
  let pkgName = pkg.name;
21401
21707
  try {
21402
21708
  const pkgJsonPath = path44.join(pkg.path, "package.json");
21403
- const pkgJson = JSON.parse(await fs40.readFile(pkgJsonPath, "utf-8"));
21709
+ const pkgJson = JSON.parse(await fs41.readFile(pkgJsonPath, "utf-8"));
21404
21710
  pkgVersion = pkgJson.version || stats.version;
21405
21711
  pkgName = pkgJson.name || pkg.name;
21406
21712
  } catch {
@@ -21465,7 +21771,7 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
21465
21771
  });
21466
21772
 
21467
21773
  // core/services/local-state-generator.ts
21468
- import fs41 from "node:fs/promises";
21774
+ import fs42 from "node:fs/promises";
21469
21775
  import path45 from "node:path";
21470
21776
  var LOCAL_STATE_FILENAME, LocalStateGenerator, localStateGenerator;
21471
21777
  var init_local_state_generator = __esm({
@@ -21483,7 +21789,7 @@ var init_local_state_generator = __esm({
21483
21789
  async generate(projectPath, state) {
21484
21790
  const filePath = path45.join(projectPath, LOCAL_STATE_FILENAME);
21485
21791
  const content = this.toMarkdown(state);
21486
- await fs41.writeFile(filePath, content, "utf-8");
21792
+ await fs42.writeFile(filePath, content, "utf-8");
21487
21793
  }
21488
21794
  /**
21489
21795
  * Remove local state file
@@ -21491,7 +21797,7 @@ var init_local_state_generator = __esm({
21491
21797
  async remove(projectPath) {
21492
21798
  const filePath = path45.join(projectPath, LOCAL_STATE_FILENAME);
21493
21799
  try {
21494
- await fs41.unlink(filePath);
21800
+ await fs42.unlink(filePath);
21495
21801
  } catch (error) {
21496
21802
  if (!isNotFoundError(error)) throw error;
21497
21803
  }
@@ -21502,7 +21808,7 @@ var init_local_state_generator = __esm({
21502
21808
  async exists(projectPath) {
21503
21809
  const filePath = path45.join(projectPath, LOCAL_STATE_FILENAME);
21504
21810
  try {
21505
- await fs41.access(filePath);
21811
+ await fs42.access(filePath);
21506
21812
  return true;
21507
21813
  } catch {
21508
21814
  return false;
@@ -21581,7 +21887,7 @@ var init_local_state_generator = __esm({
21581
21887
  });
21582
21888
 
21583
21889
  // core/services/skill-lock.ts
21584
- import fs42 from "node:fs/promises";
21890
+ import fs43 from "node:fs/promises";
21585
21891
  import os13 from "node:os";
21586
21892
  import path46 from "node:path";
21587
21893
  function getLockFilePath() {
@@ -21596,7 +21902,7 @@ function createEmptyLockFile() {
21596
21902
  }
21597
21903
  async function read() {
21598
21904
  try {
21599
- const content = await fs42.readFile(getLockFilePath(), "utf-8");
21905
+ const content = await fs43.readFile(getLockFilePath(), "utf-8");
21600
21906
  return JSON.parse(content);
21601
21907
  } catch {
21602
21908
  return createEmptyLockFile();
@@ -21604,9 +21910,9 @@ async function read() {
21604
21910
  }
21605
21911
  async function write(lockFile) {
21606
21912
  const lockPath = getLockFilePath();
21607
- await fs42.mkdir(path46.dirname(lockPath), { recursive: true });
21913
+ await fs43.mkdir(path46.dirname(lockPath), { recursive: true });
21608
21914
  lockFile.generatedAt = (/* @__PURE__ */ new Date()).toISOString();
21609
- await fs42.writeFile(lockPath, JSON.stringify(lockFile, null, 2), "utf-8");
21915
+ await fs43.writeFile(lockPath, JSON.stringify(lockFile, null, 2), "utf-8");
21610
21916
  }
21611
21917
  async function addEntry(entry) {
21612
21918
  const lockFile = await read();
@@ -21659,7 +21965,7 @@ var init_skill_lock = __esm({
21659
21965
 
21660
21966
  // core/services/skill-installer.ts
21661
21967
  import { exec as execCallback7 } from "node:child_process";
21662
- import fs43 from "node:fs/promises";
21968
+ import fs44 from "node:fs/promises";
21663
21969
  import os14 from "node:os";
21664
21970
  import path47 from "node:path";
21665
21971
  import { promisify as promisify15 } from "node:util";
@@ -21705,7 +22011,7 @@ async function discoverSkills(dir) {
21705
22011
  const skills = [];
21706
22012
  try {
21707
22013
  const rootSkill = path47.join(dir, "SKILL.md");
21708
- await fs43.access(rootSkill);
22014
+ await fs44.access(rootSkill);
21709
22015
  const dirName = path47.basename(dir);
21710
22016
  skills.push({ name: dirName, filePath: rootSkill });
21711
22017
  } catch {
@@ -21761,10 +22067,10 @@ async function installSkillFile(sourcePath, name, source, sha) {
21761
22067
  const installDir = getInstallDir();
21762
22068
  const targetDir = path47.join(installDir, name);
21763
22069
  const targetPath = path47.join(targetDir, "SKILL.md");
21764
- const content = await fs43.readFile(sourcePath, "utf-8");
22070
+ const content = await fs44.readFile(sourcePath, "utf-8");
21765
22071
  const enrichedContent = injectSourceMetadata(content, source, sha);
21766
- await fs43.mkdir(targetDir, { recursive: true });
21767
- await fs43.writeFile(targetPath, enrichedContent, "utf-8");
22072
+ await fs44.mkdir(targetDir, { recursive: true });
22073
+ await fs44.writeFile(targetPath, enrichedContent, "utf-8");
21768
22074
  return {
21769
22075
  name,
21770
22076
  filePath: targetPath,
@@ -21825,7 +22131,7 @@ async function installFromGitHub(source) {
21825
22131
  }
21826
22132
  } finally {
21827
22133
  try {
21828
- await fs43.rm(tmpDir, { recursive: true, force: true });
22134
+ await fs44.rm(tmpDir, { recursive: true, force: true });
21829
22135
  } catch {
21830
22136
  }
21831
22137
  }
@@ -21835,12 +22141,12 @@ async function installFromLocal(source) {
21835
22141
  const result = { installed: [], skipped: [], errors: [] };
21836
22142
  const localPath = source.localPath;
21837
22143
  try {
21838
- await fs43.access(localPath);
22144
+ await fs44.access(localPath);
21839
22145
  } catch {
21840
22146
  result.errors.push(`Local path not found: ${localPath}`);
21841
22147
  return result;
21842
22148
  }
21843
- const stat = await fs43.stat(localPath);
22149
+ const stat = await fs44.stat(localPath);
21844
22150
  if (stat.isFile()) {
21845
22151
  const name = path47.basename(path47.dirname(localPath));
21846
22152
  try {
@@ -21884,12 +22190,12 @@ async function remove(name) {
21884
22190
  const installDir = getInstallDir();
21885
22191
  const subdirPath = path47.join(installDir, name);
21886
22192
  try {
21887
- await fs43.rm(subdirPath, { recursive: true, force: true });
22193
+ await fs44.rm(subdirPath, { recursive: true, force: true });
21888
22194
  } catch {
21889
22195
  }
21890
22196
  const flatPath = path47.join(installDir, `${name}.md`);
21891
22197
  try {
21892
- await fs43.rm(flatPath, { force: true });
22198
+ await fs44.rm(flatPath, { force: true });
21893
22199
  } catch {
21894
22200
  }
21895
22201
  return skillLock.removeEntry(name);
@@ -21937,7 +22243,7 @@ var init_skill_installer = __esm({
21937
22243
  });
21938
22244
 
21939
22245
  // core/services/stack-detector.ts
21940
- import fs44 from "node:fs/promises";
22246
+ import fs45 from "node:fs/promises";
21941
22247
  import path48 from "node:path";
21942
22248
  var StackDetector;
21943
22249
  var init_stack_detector = __esm({
@@ -22098,7 +22404,7 @@ var init_stack_detector = __esm({
22098
22404
  async readPackageJson() {
22099
22405
  try {
22100
22406
  const pkgPath = path48.join(this.projectPath, "package.json");
22101
- const content = await fs44.readFile(pkgPath, "utf-8");
22407
+ const content = await fs45.readFile(pkgPath, "utf-8");
22102
22408
  return JSON.parse(content);
22103
22409
  } catch {
22104
22410
  return null;
@@ -22109,7 +22415,7 @@ var init_stack_detector = __esm({
22109
22415
  */
22110
22416
  async fileExists(filename) {
22111
22417
  try {
22112
- await fs44.access(path48.join(this.projectPath, filename));
22418
+ await fs45.access(path48.join(this.projectPath, filename));
22113
22419
  return true;
22114
22420
  } catch {
22115
22421
  return false;
@@ -22121,7 +22427,7 @@ var init_stack_detector = __esm({
22121
22427
 
22122
22428
  // core/services/sync-verifier.ts
22123
22429
  import { exec as exec15 } from "node:child_process";
22124
- import fs45 from "node:fs/promises";
22430
+ import fs46 from "node:fs/promises";
22125
22431
  import path49 from "node:path";
22126
22432
  import { promisify as promisify16 } from "node:util";
22127
22433
  var execAsync10, BUILTIN_CHECKS, SyncVerifier, syncVerifier;
@@ -22141,7 +22447,7 @@ var init_sync_verifier = __esm({
22141
22447
  for (const file of expected) {
22142
22448
  const filePath = path49.join(globalPath, file);
22143
22449
  try {
22144
- await fs45.access(filePath);
22450
+ await fs46.access(filePath);
22145
22451
  } catch {
22146
22452
  missing.push(file);
22147
22453
  }
@@ -22164,7 +22470,7 @@ var init_sync_verifier = __esm({
22164
22470
  for (const file of jsonFiles) {
22165
22471
  const filePath = path49.join(globalPath, file);
22166
22472
  try {
22167
- const content = await fs45.readFile(filePath, "utf-8");
22473
+ const content = await fs46.readFile(filePath, "utf-8");
22168
22474
  JSON.parse(content);
22169
22475
  } catch (error) {
22170
22476
  if (!isNotFoundError(error)) {
@@ -22193,10 +22499,10 @@ var init_sync_verifier = __esm({
22193
22499
  ];
22194
22500
  const violations = [];
22195
22501
  try {
22196
- const files = await fs45.readdir(contextDir);
22502
+ const files = await fs46.readdir(contextDir);
22197
22503
  for (const file of files) {
22198
22504
  if (!file.endsWith(".md")) continue;
22199
- const content = await fs45.readFile(path49.join(contextDir, file), "utf-8");
22505
+ const content = await fs46.readFile(path49.join(contextDir, file), "utf-8");
22200
22506
  for (const pattern of patterns) {
22201
22507
  if (pattern.test(content)) {
22202
22508
  violations.push(`${file}: potential sensitive data detected`);
@@ -22317,7 +22623,7 @@ var init_sync_verifier = __esm({
22317
22623
 
22318
22624
  // core/services/sync-service.ts
22319
22625
  import { exec as exec16 } from "node:child_process";
22320
- import fs46 from "node:fs/promises";
22626
+ import fs47 from "node:fs/promises";
22321
22627
  import os15 from "node:os";
22322
22628
  import path50 from "node:path";
22323
22629
  import { promisify as promisify17 } from "node:util";
@@ -22495,7 +22801,7 @@ var init_sync_service = __esm({
22495
22801
  async ensureDirectories() {
22496
22802
  const dirs = ["storage", "context", "agents", "memory", "analysis", "config", "sync"];
22497
22803
  await Promise.all(
22498
- dirs.map((dir) => fs46.mkdir(path50.join(this.globalPath, dir), { recursive: true }))
22804
+ dirs.map((dir) => fs47.mkdir(path50.join(this.globalPath, dir), { recursive: true }))
22499
22805
  );
22500
22806
  }
22501
22807
  // ==========================================================================
@@ -22584,7 +22890,7 @@ var init_sync_service = __esm({
22584
22890
  }
22585
22891
  try {
22586
22892
  const pkgPath = path50.join(this.projectPath, "package.json");
22587
- const pkg = JSON.parse(await fs46.readFile(pkgPath, "utf-8"));
22893
+ const pkg = JSON.parse(await fs47.readFile(pkgPath, "utf-8"));
22588
22894
  stats.version = pkg.version || "0.0.0";
22589
22895
  stats.name = pkg.name || stats.name;
22590
22896
  stats.ecosystem = "JavaScript";
@@ -22731,10 +23037,10 @@ var init_sync_service = __esm({
22731
23037
  const agents = [];
22732
23038
  const agentsPath = path50.join(this.globalPath, "agents");
22733
23039
  try {
22734
- const files = await fs46.readdir(agentsPath);
23040
+ const files = await fs47.readdir(agentsPath);
22735
23041
  for (const file of files) {
22736
23042
  if (file.endsWith(".md")) {
22737
- await fs46.unlink(path50.join(agentsPath, file));
23043
+ await fs47.unlink(path50.join(agentsPath, file));
22738
23044
  }
22739
23045
  }
22740
23046
  } catch (error) {
@@ -22792,7 +23098,7 @@ var init_sync_service = __esm({
22792
23098
  `${partialName}.md`
22793
23099
  );
22794
23100
  try {
22795
- const partialContent = await fs46.readFile(partialPath, "utf-8");
23101
+ const partialContent = await fs47.readFile(partialPath, "utf-8");
22796
23102
  resolved = resolved.replace(match[0], partialContent.trim());
22797
23103
  } catch {
22798
23104
  resolved = resolved.replace(match[0], `<!-- partial "${partialName}" not found -->`);
@@ -22812,7 +23118,7 @@ var init_sync_service = __esm({
22812
23118
  "workflow",
22813
23119
  `${name}.md`
22814
23120
  );
22815
- content = await fs46.readFile(templatePath, "utf-8");
23121
+ content = await fs47.readFile(templatePath, "utf-8");
22816
23122
  content = await this.resolveTemplateIncludes(content);
22817
23123
  } catch (error) {
22818
23124
  logger_default.debug("Workflow agent template not found, generating minimal", {
@@ -22821,7 +23127,7 @@ var init_sync_service = __esm({
22821
23127
  });
22822
23128
  content = this.generateMinimalWorkflowAgent(name);
22823
23129
  }
22824
- await fs46.writeFile(path50.join(agentsPath, `${name}.md`), content, "utf-8");
23130
+ await fs47.writeFile(path50.join(agentsPath, `${name}.md`), content, "utf-8");
22825
23131
  }
22826
23132
  async generateDomainAgent(name, agentsPath, stats, stack) {
22827
23133
  let content = "";
@@ -22835,7 +23141,7 @@ var init_sync_service = __esm({
22835
23141
  "domain",
22836
23142
  `${name}.md`
22837
23143
  );
22838
- content = await fs46.readFile(templatePath, "utf-8");
23144
+ content = await fs47.readFile(templatePath, "utf-8");
22839
23145
  content = await this.resolveTemplateIncludes(content);
22840
23146
  content = content.replace("{projectName}", stats.name);
22841
23147
  content = content.replace("{frameworks}", stack.frameworks.join(", ") || "None detected");
@@ -22847,7 +23153,7 @@ var init_sync_service = __esm({
22847
23153
  });
22848
23154
  content = this.generateMinimalDomainAgent(name, stats, stack);
22849
23155
  }
22850
- await fs46.writeFile(path50.join(agentsPath, `${name}.md`), content, "utf-8");
23156
+ await fs47.writeFile(path50.join(agentsPath, `${name}.md`), content, "utf-8");
22851
23157
  }
22852
23158
  generateMinimalWorkflowAgent(name) {
22853
23159
  const descriptions = {
@@ -22915,7 +23221,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
22915
23221
  })),
22916
23222
  agentSkillMap: Object.fromEntries(skills.map((s) => [s.agent, s.skill]))
22917
23223
  };
22918
- fs46.writeFile(
23224
+ fs47.writeFile(
22919
23225
  path50.join(this.globalPath, "config", "skills.json"),
22920
23226
  JSON.stringify(skillsConfig, null, 2),
22921
23227
  "utf-8"
@@ -22942,7 +23248,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
22942
23248
  "config",
22943
23249
  "skill-mappings.json"
22944
23250
  );
22945
- const mappingsContent = await fs46.readFile(mappingsPath, "utf-8");
23251
+ const mappingsContent = await fs47.readFile(mappingsPath, "utf-8");
22946
23252
  const mappings = JSON.parse(mappingsContent);
22947
23253
  const agentToSkillMap = mappings.agentToSkillMap || {};
22948
23254
  const packagesToInstall = [];
@@ -22962,11 +23268,11 @@ You are the ${name} expert for this project. Apply best practices for the detect
22962
23268
  const flatPath = path50.join(skillsDir, `${skillName}.md`);
22963
23269
  let alreadyInstalled = false;
22964
23270
  try {
22965
- await fs46.access(subdirPath);
23271
+ await fs47.access(subdirPath);
22966
23272
  alreadyInstalled = true;
22967
23273
  } catch {
22968
23274
  try {
22969
- await fs46.access(flatPath);
23275
+ await fs47.access(flatPath);
22970
23276
  alreadyInstalled = true;
22971
23277
  } catch {
22972
23278
  }
@@ -23021,7 +23327,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
23021
23327
  const projectJsonPath = path50.join(this.globalPath, "project.json");
23022
23328
  let existing = {};
23023
23329
  try {
23024
- existing = JSON.parse(await fs46.readFile(projectJsonPath, "utf-8"));
23330
+ existing = JSON.parse(await fs47.readFile(projectJsonPath, "utf-8"));
23025
23331
  } catch (error) {
23026
23332
  logger_default.debug("No existing project.json", {
23027
23333
  path: projectJsonPath,
@@ -23047,7 +23353,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
23047
23353
  lastSyncCommit: git.recentCommits[0]?.hash || null,
23048
23354
  lastSyncBranch: git.branch
23049
23355
  };
23050
- await fs46.writeFile(projectJsonPath, JSON.stringify(updated, null, 2), "utf-8");
23356
+ await fs47.writeFile(projectJsonPath, JSON.stringify(updated, null, 2), "utf-8");
23051
23357
  }
23052
23358
  // ==========================================================================
23053
23359
  // STATE.JSON UPDATE
@@ -23056,7 +23362,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
23056
23362
  const statePath = path50.join(this.globalPath, "storage", "state.json");
23057
23363
  let state = {};
23058
23364
  try {
23059
- state = JSON.parse(await fs46.readFile(statePath, "utf-8"));
23365
+ state = JSON.parse(await fs47.readFile(statePath, "utf-8"));
23060
23366
  } catch (error) {
23061
23367
  logger_default.debug("No existing state.json", { path: statePath, error: getErrorMessage(error) });
23062
23368
  }
@@ -23084,7 +23390,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
23084
23390
  lastAction: "Synced project",
23085
23391
  nextAction: 'Run `p. task "description"` to start working'
23086
23392
  };
23087
- await fs46.writeFile(statePath, JSON.stringify(state, null, 2), "utf-8");
23393
+ await fs47.writeFile(statePath, JSON.stringify(state, null, 2), "utf-8");
23088
23394
  try {
23089
23395
  await localStateGenerator.generate(
23090
23396
  this.projectPath,
@@ -23107,7 +23413,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
23107
23413
  fileCount: stats.fileCount,
23108
23414
  commitCount: git.commits
23109
23415
  };
23110
- await fs46.appendFile(memoryPath, `${JSON.stringify(event)}
23416
+ await fs47.appendFile(memoryPath, `${JSON.stringify(event)}
23111
23417
  `, "utf-8");
23112
23418
  }
23113
23419
  // ==========================================================================
@@ -23128,7 +23434,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
23128
23434
  for (const file of contextFiles) {
23129
23435
  try {
23130
23436
  const filePath = path50.join(this.globalPath, file);
23131
- const content = await fs46.readFile(filePath, "utf-8");
23437
+ const content = await fs47.readFile(filePath, "utf-8");
23132
23438
  filteredChars += content.length;
23133
23439
  } catch (error) {
23134
23440
  logger_default.debug("Context file not found for metrics", { file, error: getErrorMessage(error) });
@@ -23137,7 +23443,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
23137
23443
  for (const agent of agents) {
23138
23444
  try {
23139
23445
  const agentPath = path50.join(this.globalPath, "agents", `${agent.name}.md`);
23140
- const content = await fs46.readFile(agentPath, "utf-8");
23446
+ const content = await fs47.readFile(agentPath, "utf-8");
23141
23447
  filteredChars += content.length;
23142
23448
  } catch (error) {
23143
23449
  logger_default.debug("Agent file not found for metrics", {
@@ -23173,7 +23479,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
23173
23479
  // ==========================================================================
23174
23480
  async fileExists(filename) {
23175
23481
  try {
23176
- await fs46.access(path50.join(this.projectPath, filename));
23482
+ await fs47.access(path50.join(this.projectPath, filename));
23177
23483
  return true;
23178
23484
  } catch (error) {
23179
23485
  logger_default.debug("File not found", { filename, error: getErrorMessage(error) });
@@ -23183,7 +23489,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
23183
23489
  async getCliVersion() {
23184
23490
  try {
23185
23491
  const pkgPath = path50.join(__dirname, "..", "..", "package.json");
23186
- const pkg = JSON.parse(await fs46.readFile(pkgPath, "utf-8"));
23492
+ const pkg = JSON.parse(await fs47.readFile(pkgPath, "utf-8"));
23187
23493
  return pkg.version || "0.0.0";
23188
23494
  } catch (error) {
23189
23495
  logger_default.debug("Failed to read CLI version", { error: getErrorMessage(error) });
@@ -23344,7 +23650,7 @@ __export(uninstall_exports, {
23344
23650
  uninstall: () => uninstall
23345
23651
  });
23346
23652
  import { execSync as execSync3 } from "node:child_process";
23347
- import fs47 from "node:fs/promises";
23653
+ import fs48 from "node:fs/promises";
23348
23654
  import os16 from "node:os";
23349
23655
  import path51 from "node:path";
23350
23656
  import readline2 from "node:readline";
@@ -23352,14 +23658,14 @@ import chalk12 from "chalk";
23352
23658
  async function getDirectorySize(dirPath) {
23353
23659
  let totalSize = 0;
23354
23660
  try {
23355
- const entries = await fs47.readdir(dirPath, { withFileTypes: true });
23661
+ const entries = await fs48.readdir(dirPath, { withFileTypes: true });
23356
23662
  for (const entry of entries) {
23357
23663
  const entryPath = path51.join(dirPath, entry.name);
23358
23664
  if (entry.isDirectory()) {
23359
23665
  totalSize += await getDirectorySize(entryPath);
23360
23666
  } else {
23361
23667
  try {
23362
- const stats = await fs47.stat(entryPath);
23668
+ const stats = await fs48.stat(entryPath);
23363
23669
  totalSize += stats.size;
23364
23670
  } catch {
23365
23671
  }
@@ -23378,7 +23684,7 @@ function formatSize(bytes) {
23378
23684
  }
23379
23685
  async function countDirectoryItems(dirPath) {
23380
23686
  try {
23381
- const entries = await fs47.readdir(dirPath, { withFileTypes: true });
23687
+ const entries = await fs48.readdir(dirPath, { withFileTypes: true });
23382
23688
  return entries.filter((e) => e.isDirectory()).length;
23383
23689
  } catch {
23384
23690
  return 0;
@@ -23426,7 +23732,7 @@ async function gatherUninstallItems() {
23426
23732
  let hasPrjctSection = false;
23427
23733
  if (claudeMdExists) {
23428
23734
  try {
23429
- const content = await fs47.readFile(claudeMdPath, "utf-8");
23735
+ const content = await fs48.readFile(claudeMdPath, "utf-8");
23430
23736
  hasPrjctSection = content.includes(PRJCT_START_MARKER) && content.includes(PRJCT_END_MARKER);
23431
23737
  } catch {
23432
23738
  }
@@ -23476,7 +23782,7 @@ async function gatherUninstallItems() {
23476
23782
  let hasGeminiPrjctSection = false;
23477
23783
  if (geminiMdExists) {
23478
23784
  try {
23479
- const content = await fs47.readFile(geminiMdPath, "utf-8");
23785
+ const content = await fs48.readFile(geminiMdPath, "utf-8");
23480
23786
  hasGeminiPrjctSection = content.includes(PRJCT_START_MARKER) && content.includes(PRJCT_END_MARKER);
23481
23787
  } catch {
23482
23788
  }
@@ -23493,7 +23799,7 @@ async function gatherUninstallItems() {
23493
23799
  }
23494
23800
  async function removePrjctSection(filePath) {
23495
23801
  try {
23496
- const content = await fs47.readFile(filePath, "utf-8");
23802
+ const content = await fs48.readFile(filePath, "utf-8");
23497
23803
  if (!content.includes(PRJCT_START_MARKER) || !content.includes(PRJCT_END_MARKER)) {
23498
23804
  return false;
23499
23805
  }
@@ -23502,9 +23808,9 @@ async function removePrjctSection(filePath) {
23502
23808
  let newContent = content.substring(0, startIndex) + content.substring(endIndex);
23503
23809
  newContent = newContent.replace(/\n{3,}/g, "\n\n").trim();
23504
23810
  if (!newContent || newContent.trim().length === 0) {
23505
- await fs47.unlink(filePath);
23811
+ await fs48.unlink(filePath);
23506
23812
  } else {
23507
- await fs47.writeFile(filePath, `${newContent}
23813
+ await fs48.writeFile(filePath, `${newContent}
23508
23814
  `, "utf-8");
23509
23815
  }
23510
23816
  return true;
@@ -23512,12 +23818,12 @@ async function removePrjctSection(filePath) {
23512
23818
  return false;
23513
23819
  }
23514
23820
  }
23515
- async function createBackup() {
23821
+ async function createBackup2() {
23516
23822
  const homeDir = os16.homedir();
23517
23823
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
23518
23824
  const backupDir = path51.join(homeDir, `.prjct-backup-${timestamp}`);
23519
23825
  try {
23520
- await fs47.mkdir(backupDir, { recursive: true });
23826
+ await fs48.mkdir(backupDir, { recursive: true });
23521
23827
  const prjctCliPath = path_manager_default.getGlobalBasePath();
23522
23828
  if (await fileExists(prjctCliPath)) {
23523
23829
  await copyDirectory(prjctCliPath, path51.join(backupDir, ".prjct-cli"));
@@ -23528,15 +23834,15 @@ async function createBackup() {
23528
23834
  }
23529
23835
  }
23530
23836
  async function copyDirectory(src, dest) {
23531
- await fs47.mkdir(dest, { recursive: true });
23532
- const entries = await fs47.readdir(src, { withFileTypes: true });
23837
+ await fs48.mkdir(dest, { recursive: true });
23838
+ const entries = await fs48.readdir(src, { withFileTypes: true });
23533
23839
  for (const entry of entries) {
23534
23840
  const srcPath = path51.join(src, entry.name);
23535
23841
  const destPath = path51.join(dest, entry.name);
23536
23842
  if (entry.isDirectory()) {
23537
23843
  await copyDirectory(srcPath, destPath);
23538
23844
  } else {
23539
- await fs47.copyFile(srcPath, destPath);
23845
+ await fs48.copyFile(srcPath, destPath);
23540
23846
  }
23541
23847
  }
23542
23848
  }
@@ -23552,10 +23858,10 @@ async function performUninstall(items, installation, options) {
23552
23858
  deleted.push(item.path);
23553
23859
  }
23554
23860
  } else if (item.type === "directory") {
23555
- await fs47.rm(item.path, { recursive: true, force: true });
23861
+ await fs48.rm(item.path, { recursive: true, force: true });
23556
23862
  deleted.push(item.path);
23557
23863
  } else if (item.type === "file") {
23558
- await fs47.unlink(item.path);
23864
+ await fs48.unlink(item.path);
23559
23865
  deleted.push(item.path);
23560
23866
  }
23561
23867
  } catch (error) {
@@ -23649,7 +23955,7 @@ async function uninstall(options = {}, _projectPath = process.cwd()) {
23649
23955
  }
23650
23956
  if (options.backup) {
23651
23957
  console.log(chalk12.blue("Creating backup..."));
23652
- const backupPath = await createBackup();
23958
+ const backupPath = await createBackup2();
23653
23959
  if (backupPath) {
23654
23960
  console.log(chalk12.green(`Backup created: ${path_manager_default.getDisplayPath(backupPath)}`));
23655
23961
  console.log("");
@@ -23710,7 +24016,7 @@ var init_uninstall = __esm({
23710
24016
  __name(detectInstallation, "detectInstallation");
23711
24017
  __name(gatherUninstallItems, "gatherUninstallItems");
23712
24018
  __name(removePrjctSection, "removePrjctSection");
23713
- __name(createBackup, "createBackup");
24019
+ __name(createBackup2, "createBackup");
23714
24020
  __name(copyDirectory, "copyDirectory");
23715
24021
  __name(performUninstall, "performUninstall");
23716
24022
  __name(promptConfirmation, "promptConfirmation");
@@ -24621,7 +24927,7 @@ __export(setup_exports, {
24621
24927
  run: () => run
24622
24928
  });
24623
24929
  import { execSync as execSync4 } from "node:child_process";
24624
- import fs48 from "node:fs/promises";
24930
+ import fs49 from "node:fs/promises";
24625
24931
  import os17 from "node:os";
24626
24932
  import path53 from "node:path";
24627
24933
  import chalk15 from "chalk";
@@ -24765,9 +25071,9 @@ async function installGeminiRouter() {
24765
25071
  const geminiCommandsDir = path53.join(os17.homedir(), ".gemini", "commands");
24766
25072
  const routerSource = path53.join(PACKAGE_ROOT, "templates", "commands", "p.toml");
24767
25073
  const routerDest = path53.join(geminiCommandsDir, "p.toml");
24768
- await fs48.mkdir(geminiCommandsDir, { recursive: true });
25074
+ await fs49.mkdir(geminiCommandsDir, { recursive: true });
24769
25075
  if (await fileExists(routerSource)) {
24770
- await fs48.copyFile(routerSource, routerDest);
25076
+ await fs49.copyFile(routerSource, routerDest);
24771
25077
  return true;
24772
25078
  }
24773
25079
  return false;
@@ -24781,12 +25087,12 @@ async function installGeminiGlobalConfig() {
24781
25087
  const geminiDir = path53.join(os17.homedir(), ".gemini");
24782
25088
  const globalConfigPath = path53.join(geminiDir, "GEMINI.md");
24783
25089
  const templatePath = path53.join(PACKAGE_ROOT, "templates", "global", "GEMINI.md");
24784
- await fs48.mkdir(geminiDir, { recursive: true });
24785
- const templateContent = await fs48.readFile(templatePath, "utf-8");
25090
+ await fs49.mkdir(geminiDir, { recursive: true });
25091
+ const templateContent = await fs49.readFile(templatePath, "utf-8");
24786
25092
  let existingContent = "";
24787
25093
  let configExists = false;
24788
25094
  try {
24789
- existingContent = await fs48.readFile(globalConfigPath, "utf-8");
25095
+ existingContent = await fs49.readFile(globalConfigPath, "utf-8");
24790
25096
  configExists = true;
24791
25097
  } catch (error) {
24792
25098
  if (isNotFoundError(error)) {
@@ -24796,7 +25102,7 @@ async function installGeminiGlobalConfig() {
24796
25102
  }
24797
25103
  }
24798
25104
  if (!configExists) {
24799
- await fs48.writeFile(globalConfigPath, templateContent, "utf-8");
25105
+ await fs49.writeFile(globalConfigPath, templateContent, "utf-8");
24800
25106
  return { success: true, action: "created" };
24801
25107
  }
24802
25108
  const startMarker = "<!-- prjct:start - DO NOT REMOVE THIS MARKER -->";
@@ -24806,7 +25112,7 @@ async function installGeminiGlobalConfig() {
24806
25112
  const updatedContent2 = `${existingContent}
24807
25113
 
24808
25114
  ${templateContent}`;
24809
- await fs48.writeFile(globalConfigPath, updatedContent2, "utf-8");
25115
+ await fs49.writeFile(globalConfigPath, updatedContent2, "utf-8");
24810
25116
  return { success: true, action: "appended" };
24811
25117
  }
24812
25118
  const beforeMarker = existingContent.substring(0, existingContent.indexOf(startMarker));
@@ -24818,7 +25124,7 @@ ${templateContent}`;
24818
25124
  templateContent.indexOf(endMarker) + endMarker.length
24819
25125
  );
24820
25126
  const updatedContent = beforeMarker + prjctSection + afterMarker;
24821
- await fs48.writeFile(globalConfigPath, updatedContent, "utf-8");
25127
+ await fs49.writeFile(globalConfigPath, updatedContent, "utf-8");
24822
25128
  return { success: true, action: "updated" };
24823
25129
  } catch (error) {
24824
25130
  logger_default.warn(`Gemini config warning: ${getErrorMessage2(error)}`);
@@ -24831,14 +25137,14 @@ async function installAntigravitySkill() {
24831
25137
  const prjctSkillDir = path53.join(antigravitySkillsDir, "prjct");
24832
25138
  const skillMdPath = path53.join(prjctSkillDir, "SKILL.md");
24833
25139
  const templatePath = path53.join(PACKAGE_ROOT, "templates", "antigravity", "SKILL.md");
24834
- await fs48.mkdir(prjctSkillDir, { recursive: true });
25140
+ await fs49.mkdir(prjctSkillDir, { recursive: true });
24835
25141
  const skillExists = await fileExists(skillMdPath);
24836
25142
  if (!await fileExists(templatePath)) {
24837
25143
  logger_default.warn("Antigravity SKILL.md template not found");
24838
25144
  return { success: false, action: null };
24839
25145
  }
24840
- const templateContent = await fs48.readFile(templatePath, "utf-8");
24841
- await fs48.writeFile(skillMdPath, templateContent, "utf-8");
25146
+ const templateContent = await fs49.readFile(templatePath, "utf-8");
25147
+ await fs49.writeFile(skillMdPath, templateContent, "utf-8");
24842
25148
  return { success: true, action: skillExists ? "updated" : "created" };
24843
25149
  } catch (error) {
24844
25150
  logger_default.warn(`Antigravity skill warning: ${getErrorMessage2(error)}`);
@@ -24863,18 +25169,18 @@ async function installCursorProject(projectRoot) {
24863
25169
  const routerMdcDest = path53.join(rulesDir, "prjct.mdc");
24864
25170
  const routerMdcSource = path53.join(PACKAGE_ROOT, "templates", "cursor", "router.mdc");
24865
25171
  const cursorCommandsSource = path53.join(PACKAGE_ROOT, "templates", "cursor", "commands");
24866
- await fs48.mkdir(rulesDir, { recursive: true });
24867
- await fs48.mkdir(commandsDir, { recursive: true });
25172
+ await fs49.mkdir(rulesDir, { recursive: true });
25173
+ await fs49.mkdir(commandsDir, { recursive: true });
24868
25174
  if (await fileExists(routerMdcSource)) {
24869
- await fs48.copyFile(routerMdcSource, routerMdcDest);
25175
+ await fs49.copyFile(routerMdcSource, routerMdcDest);
24870
25176
  result.rulesCreated = true;
24871
25177
  }
24872
25178
  if (await fileExists(cursorCommandsSource)) {
24873
- const commandFiles = (await fs48.readdir(cursorCommandsSource)).filter((f) => f.endsWith(".md"));
25179
+ const commandFiles = (await fs49.readdir(cursorCommandsSource)).filter((f) => f.endsWith(".md"));
24874
25180
  for (const file of commandFiles) {
24875
25181
  const src = path53.join(cursorCommandsSource, file);
24876
25182
  const dest = path53.join(commandsDir, file);
24877
- await fs48.copyFile(src, dest);
25183
+ await fs49.copyFile(src, dest);
24878
25184
  }
24879
25185
  result.commandsCreated = commandFiles.length > 0;
24880
25186
  }
@@ -24903,7 +25209,7 @@ async function addCursorToGitignore(projectRoot) {
24903
25209
  let content = "";
24904
25210
  let configExists = false;
24905
25211
  try {
24906
- content = await fs48.readFile(gitignorePath, "utf-8");
25212
+ content = await fs49.readFile(gitignorePath, "utf-8");
24907
25213
  configExists = true;
24908
25214
  } catch (error) {
24909
25215
  if (!isNotFoundError(error)) {
@@ -24918,7 +25224,7 @@ async function addCursorToGitignore(projectRoot) {
24918
25224
  ${entriesToAdd.join("\n")}
24919
25225
  ` : `${entriesToAdd.join("\n")}
24920
25226
  `;
24921
- await fs48.writeFile(gitignorePath, newContent, "utf-8");
25227
+ await fs49.writeFile(gitignorePath, newContent, "utf-8");
24922
25228
  return true;
24923
25229
  } catch (error) {
24924
25230
  logger_default.warn(`Gitignore update warning: ${getErrorMessage2(error)}`);
@@ -24947,20 +25253,20 @@ async function installWindsurfProject(projectRoot) {
24947
25253
  const routerDest = path53.join(rulesDir, "prjct.md");
24948
25254
  const routerSource = path53.join(PACKAGE_ROOT, "templates", "windsurf", "router.md");
24949
25255
  const windsurfWorkflowsSource = path53.join(PACKAGE_ROOT, "templates", "windsurf", "workflows");
24950
- await fs48.mkdir(rulesDir, { recursive: true });
24951
- await fs48.mkdir(workflowsDir, { recursive: true });
25256
+ await fs49.mkdir(rulesDir, { recursive: true });
25257
+ await fs49.mkdir(workflowsDir, { recursive: true });
24952
25258
  if (await fileExists(routerSource)) {
24953
- await fs48.copyFile(routerSource, routerDest);
25259
+ await fs49.copyFile(routerSource, routerDest);
24954
25260
  result.rulesCreated = true;
24955
25261
  }
24956
25262
  if (await fileExists(windsurfWorkflowsSource)) {
24957
- const workflowFiles = (await fs48.readdir(windsurfWorkflowsSource)).filter(
25263
+ const workflowFiles = (await fs49.readdir(windsurfWorkflowsSource)).filter(
24958
25264
  (f) => f.endsWith(".md")
24959
25265
  );
24960
25266
  for (const file of workflowFiles) {
24961
25267
  const src = path53.join(windsurfWorkflowsSource, file);
24962
25268
  const dest = path53.join(workflowsDir, file);
24963
- await fs48.copyFile(src, dest);
25269
+ await fs49.copyFile(src, dest);
24964
25270
  }
24965
25271
  result.workflowsCreated = workflowFiles.length > 0;
24966
25272
  }
@@ -24989,7 +25295,7 @@ async function addWindsurfToGitignore(projectRoot) {
24989
25295
  let content = "";
24990
25296
  let configExists = false;
24991
25297
  try {
24992
- content = await fs48.readFile(gitignorePath, "utf-8");
25298
+ content = await fs49.readFile(gitignorePath, "utf-8");
24993
25299
  configExists = true;
24994
25300
  } catch (error) {
24995
25301
  if (!isNotFoundError(error)) {
@@ -25004,7 +25310,7 @@ async function addWindsurfToGitignore(projectRoot) {
25004
25310
  ${entriesToAdd.join("\n")}
25005
25311
  ` : `${entriesToAdd.join("\n")}
25006
25312
  `;
25007
- await fs48.writeFile(gitignorePath, newContent, "utf-8");
25313
+ await fs49.writeFile(gitignorePath, newContent, "utf-8");
25008
25314
  return true;
25009
25315
  } catch (error) {
25010
25316
  logger_default.warn(`Gitignore update warning: ${getErrorMessage2(error)}`);
@@ -25025,7 +25331,7 @@ async function migrateProjectsCliVersion() {
25025
25331
  if (!await fileExists(projectsDir)) {
25026
25332
  return;
25027
25333
  }
25028
- const projectDirs = (await fs48.readdir(projectsDir, { withFileTypes: true })).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
25334
+ const projectDirs = (await fs49.readdir(projectsDir, { withFileTypes: true })).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
25029
25335
  let migrated = 0;
25030
25336
  for (const projectId of projectDirs) {
25031
25337
  const projectJsonPath = path53.join(projectsDir, projectId, "project.json");
@@ -25033,11 +25339,11 @@ async function migrateProjectsCliVersion() {
25033
25339
  continue;
25034
25340
  }
25035
25341
  try {
25036
- const content = await fs48.readFile(projectJsonPath, "utf8");
25342
+ const content = await fs49.readFile(projectJsonPath, "utf8");
25037
25343
  const project = JSON.parse(content);
25038
25344
  if (project.cliVersion !== VERSION) {
25039
25345
  project.cliVersion = VERSION;
25040
- await fs48.writeFile(projectJsonPath, JSON.stringify(project, null, 2));
25346
+ await fs49.writeFile(projectJsonPath, JSON.stringify(project, null, 2));
25041
25347
  migrated++;
25042
25348
  }
25043
25349
  } catch (error) {
@@ -25059,7 +25365,7 @@ async function ensureStatusLineSettings(settingsPath, statusLinePath) {
25059
25365
  let settings = {};
25060
25366
  if (await fileExists(settingsPath)) {
25061
25367
  try {
25062
- settings = JSON.parse(await fs48.readFile(settingsPath, "utf8"));
25368
+ settings = JSON.parse(await fs49.readFile(settingsPath, "utf8"));
25063
25369
  } catch (error) {
25064
25370
  if (!(error instanceof SyntaxError)) {
25065
25371
  throw error;
@@ -25067,7 +25373,7 @@ async function ensureStatusLineSettings(settingsPath, statusLinePath) {
25067
25373
  }
25068
25374
  }
25069
25375
  settings.statusLine = { type: "command", command: statusLinePath };
25070
- await fs48.writeFile(settingsPath, JSON.stringify(settings, null, 2));
25376
+ await fs49.writeFile(settingsPath, JSON.stringify(settings, null, 2));
25071
25377
  }
25072
25378
  async function installStatusLine() {
25073
25379
  try {
@@ -25087,22 +25393,22 @@ async function installStatusLine() {
25087
25393
  const sourceComponentsDir = path53.join(assetsDir, "components");
25088
25394
  const sourceConfigPath = path53.join(assetsDir, "default-config.json");
25089
25395
  if (!await fileExists(claudeDir)) {
25090
- await fs48.mkdir(claudeDir, { recursive: true });
25396
+ await fs49.mkdir(claudeDir, { recursive: true });
25091
25397
  }
25092
25398
  if (!await fileExists(prjctStatusLineDir)) {
25093
- await fs48.mkdir(prjctStatusLineDir, { recursive: true });
25399
+ await fs49.mkdir(prjctStatusLineDir, { recursive: true });
25094
25400
  }
25095
25401
  if (!await fileExists(prjctThemesDir)) {
25096
- await fs48.mkdir(prjctThemesDir, { recursive: true });
25402
+ await fs49.mkdir(prjctThemesDir, { recursive: true });
25097
25403
  }
25098
25404
  if (!await fileExists(prjctLibDir)) {
25099
- await fs48.mkdir(prjctLibDir, { recursive: true });
25405
+ await fs49.mkdir(prjctLibDir, { recursive: true });
25100
25406
  }
25101
25407
  if (!await fileExists(prjctComponentsDir)) {
25102
- await fs48.mkdir(prjctComponentsDir, { recursive: true });
25408
+ await fs49.mkdir(prjctComponentsDir, { recursive: true });
25103
25409
  }
25104
25410
  if (await fileExists(prjctStatusLinePath)) {
25105
- const existingContent = await fs48.readFile(prjctStatusLinePath, "utf8");
25411
+ const existingContent = await fs49.readFile(prjctStatusLinePath, "utf8");
25106
25412
  if (existingContent.includes("CLI_VERSION=")) {
25107
25413
  const versionMatch = existingContent.match(/CLI_VERSION="([^"]*)"/);
25108
25414
  if (versionMatch && versionMatch[1] !== VERSION) {
@@ -25110,7 +25416,7 @@ async function installStatusLine() {
25110
25416
  /CLI_VERSION="[^"]*"/,
25111
25417
  `CLI_VERSION="${VERSION}"`
25112
25418
  );
25113
- await fs48.writeFile(prjctStatusLinePath, updatedContent, { mode: 493 });
25419
+ await fs49.writeFile(prjctStatusLinePath, updatedContent, { mode: 493 });
25114
25420
  }
25115
25421
  await installStatusLineModules(sourceLibDir, prjctLibDir);
25116
25422
  await installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
@@ -25120,21 +25426,21 @@ async function installStatusLine() {
25120
25426
  }
25121
25427
  }
25122
25428
  if (await fileExists(sourceScript)) {
25123
- let scriptContent = await fs48.readFile(sourceScript, "utf8");
25429
+ let scriptContent = await fs49.readFile(sourceScript, "utf8");
25124
25430
  scriptContent = scriptContent.replace(/CLI_VERSION="[^"]*"/, `CLI_VERSION="${VERSION}"`);
25125
- await fs48.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
25431
+ await fs49.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
25126
25432
  await installStatusLineModules(sourceLibDir, prjctLibDir);
25127
25433
  await installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
25128
25434
  if (await fileExists(sourceThemeDir)) {
25129
- const themes = await fs48.readdir(sourceThemeDir);
25435
+ const themes = await fs49.readdir(sourceThemeDir);
25130
25436
  for (const theme of themes) {
25131
25437
  const src = path53.join(sourceThemeDir, theme);
25132
25438
  const dest = path53.join(prjctThemesDir, theme);
25133
- await fs48.copyFile(src, dest);
25439
+ await fs49.copyFile(src, dest);
25134
25440
  }
25135
25441
  }
25136
25442
  if (!await fileExists(prjctConfigPath) && await fileExists(sourceConfigPath)) {
25137
- await fs48.copyFile(sourceConfigPath, prjctConfigPath);
25443
+ await fs49.copyFile(sourceConfigPath, prjctConfigPath);
25138
25444
  }
25139
25445
  } else {
25140
25446
  const scriptContent = `#!/bin/bash
@@ -25169,7 +25475,7 @@ if [ -f "$CONFIG" ]; then
25169
25475
  fi
25170
25476
  echo "prjct"
25171
25477
  `;
25172
- await fs48.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
25478
+ await fs49.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
25173
25479
  }
25174
25480
  await ensureStatusLineSymlink(claudeStatusLinePath, prjctStatusLinePath);
25175
25481
  await ensureStatusLineSettings(settingsPath, claudeStatusLinePath);
@@ -25184,7 +25490,7 @@ async function installContext7MCP() {
25184
25490
  const claudeDir = path53.join(os17.homedir(), ".claude");
25185
25491
  const mcpConfigPath = path53.join(claudeDir, "mcp.json");
25186
25492
  if (!await fileExists(claudeDir)) {
25187
- await fs48.mkdir(claudeDir, { recursive: true });
25493
+ await fs49.mkdir(claudeDir, { recursive: true });
25188
25494
  }
25189
25495
  const context7Config = {
25190
25496
  mcpServers: {
@@ -25195,16 +25501,16 @@ async function installContext7MCP() {
25195
25501
  }
25196
25502
  };
25197
25503
  if (await fileExists(mcpConfigPath)) {
25198
- const existingContent = await fs48.readFile(mcpConfigPath, "utf-8");
25504
+ const existingContent = await fs49.readFile(mcpConfigPath, "utf-8");
25199
25505
  const existingConfig = JSON.parse(existingContent);
25200
25506
  if (existingConfig.mcpServers?.context7) {
25201
25507
  return;
25202
25508
  }
25203
25509
  existingConfig.mcpServers = existingConfig.mcpServers || {};
25204
25510
  existingConfig.mcpServers.context7 = context7Config.mcpServers.context7;
25205
- await fs48.writeFile(mcpConfigPath, JSON.stringify(existingConfig, null, 2), "utf-8");
25511
+ await fs49.writeFile(mcpConfigPath, JSON.stringify(existingConfig, null, 2), "utf-8");
25206
25512
  } else {
25207
- await fs48.writeFile(mcpConfigPath, JSON.stringify(context7Config, null, 2), "utf-8");
25513
+ await fs49.writeFile(mcpConfigPath, JSON.stringify(context7Config, null, 2), "utf-8");
25208
25514
  }
25209
25515
  } catch (error) {
25210
25516
  logger_default.warn(`Context7 MCP setup warning: ${getErrorMessage2(error)}`);
@@ -25214,34 +25520,34 @@ async function installStatusLineModules(sourceDir, destDir) {
25214
25520
  if (!await fileExists(sourceDir)) {
25215
25521
  return;
25216
25522
  }
25217
- const files = await fs48.readdir(sourceDir);
25523
+ const files = await fs49.readdir(sourceDir);
25218
25524
  for (const file of files) {
25219
25525
  if (file.endsWith(".sh")) {
25220
25526
  const src = path53.join(sourceDir, file);
25221
25527
  const dest = path53.join(destDir, file);
25222
- await fs48.copyFile(src, dest);
25223
- await fs48.chmod(dest, 493);
25528
+ await fs49.copyFile(src, dest);
25529
+ await fs49.chmod(dest, 493);
25224
25530
  }
25225
25531
  }
25226
25532
  }
25227
25533
  async function ensureStatusLineSymlink(linkPath, targetPath) {
25228
25534
  try {
25229
25535
  if (await fileExists(linkPath)) {
25230
- const stats = await fs48.lstat(linkPath);
25536
+ const stats = await fs49.lstat(linkPath);
25231
25537
  if (stats.isSymbolicLink()) {
25232
- const existingTarget = await fs48.readlink(linkPath);
25538
+ const existingTarget = await fs49.readlink(linkPath);
25233
25539
  if (existingTarget === targetPath) {
25234
25540
  return;
25235
25541
  }
25236
25542
  }
25237
- await fs48.unlink(linkPath);
25543
+ await fs49.unlink(linkPath);
25238
25544
  }
25239
- await fs48.symlink(targetPath, linkPath);
25545
+ await fs49.symlink(targetPath, linkPath);
25240
25546
  } catch (_error) {
25241
25547
  try {
25242
25548
  if (await fileExists(targetPath)) {
25243
- await fs48.copyFile(targetPath, linkPath);
25244
- await fs48.chmod(linkPath, 493);
25549
+ await fs49.copyFile(targetPath, linkPath);
25550
+ await fs49.chmod(linkPath, 493);
25245
25551
  }
25246
25552
  } catch (copyError) {
25247
25553
  if (!isNotFoundError(copyError)) {
@@ -25935,7 +26241,7 @@ ${"\u2550".repeat(50)}
25935
26241
  });
25936
26242
 
25937
26243
  // core/commands/context.ts
25938
- import fs49 from "node:fs/promises";
26244
+ import fs50 from "node:fs/promises";
25939
26245
  import path55 from "node:path";
25940
26246
  var ContextCommands, contextCommands;
25941
26247
  var init_context = __esm({
@@ -26063,7 +26369,7 @@ var init_context = __esm({
26063
26369
  async loadRepoAnalysis(globalPath) {
26064
26370
  try {
26065
26371
  const analysisPath = path55.join(globalPath, "analysis", "repo-analysis.json");
26066
- const content = await fs49.readFile(analysisPath, "utf-8");
26372
+ const content = await fs50.readFile(analysisPath, "utf-8");
26067
26373
  const data = JSON.parse(content);
26068
26374
  return {
26069
26375
  ecosystem: data.ecosystem || "unknown",
@@ -26560,7 +26866,7 @@ var init_maintenance = __esm({
26560
26866
  });
26561
26867
 
26562
26868
  // core/commands/setup.ts
26563
- import fs50 from "node:fs/promises";
26869
+ import fs51 from "node:fs/promises";
26564
26870
  import path59 from "node:path";
26565
26871
  import chalk16 from "chalk";
26566
26872
  var SetupCommands;
@@ -26748,11 +27054,11 @@ fi
26748
27054
  # Default: show prjct branding
26749
27055
  echo "\u26A1 prjct"
26750
27056
  `;
26751
- await fs50.writeFile(statusLinePath, scriptContent, { mode: 493 });
27057
+ await fs51.writeFile(statusLinePath, scriptContent, { mode: 493 });
26752
27058
  let settings = {};
26753
27059
  if (await fileExists(settingsPath)) {
26754
27060
  try {
26755
- settings = JSON.parse(await fs50.readFile(settingsPath, "utf8"));
27061
+ settings = JSON.parse(await fs51.readFile(settingsPath, "utf8"));
26756
27062
  } catch (_error) {
26757
27063
  }
26758
27064
  }
@@ -26760,7 +27066,7 @@ echo "\u26A1 prjct"
26760
27066
  type: "command",
26761
27067
  command: statusLinePath
26762
27068
  };
26763
- await fs50.writeFile(settingsPath, JSON.stringify(settings, null, 2));
27069
+ await fs51.writeFile(settingsPath, JSON.stringify(settings, null, 2));
26764
27070
  return { success: true };
26765
27071
  } catch (error) {
26766
27072
  return { success: false, error: getErrorMessage2(error) };
@@ -28118,7 +28424,7 @@ var init_linear = __esm({
28118
28424
  });
28119
28425
 
28120
28426
  // core/utils/project-credentials.ts
28121
- import fs51 from "node:fs/promises";
28427
+ import fs52 from "node:fs/promises";
28122
28428
  import os18 from "node:os";
28123
28429
  import path62 from "node:path";
28124
28430
  function getCredentialsPath(projectId) {
@@ -28130,7 +28436,7 @@ async function getProjectCredentials(projectId) {
28130
28436
  return {};
28131
28437
  }
28132
28438
  try {
28133
- return JSON.parse(await fs51.readFile(credPath, "utf-8"));
28439
+ return JSON.parse(await fs52.readFile(credPath, "utf-8"));
28134
28440
  } catch (error) {
28135
28441
  console.error("[project-credentials] Failed to read credentials:", getErrorMessage2(error));
28136
28442
  return {};
@@ -28710,7 +29016,7 @@ var require_package = __commonJS({
28710
29016
  "package.json"(exports, module) {
28711
29017
  module.exports = {
28712
29018
  name: "prjct-cli",
28713
- version: "1.7.0",
29019
+ version: "1.7.2",
28714
29020
  description: "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
28715
29021
  main: "core/index.ts",
28716
29022
  bin: {
@@ -29185,7 +29491,7 @@ __name(isBun, "isBun");
29185
29491
  init_path_manager();
29186
29492
  init_fs();
29187
29493
  init_logger();
29188
- import fs8 from "node:fs/promises";
29494
+ import fs9 from "node:fs/promises";
29189
29495
  import path8 from "node:path";
29190
29496
  import { Hono } from "hono";
29191
29497
  import * as jsonc2 from "jsonc-parser";
@@ -29198,7 +29504,7 @@ var STORAGE_PATHS = {
29198
29504
  };
29199
29505
  async function readJsonFile(filePath) {
29200
29506
  try {
29201
- const content = await fs8.readFile(filePath, "utf-8");
29507
+ const content = await fs9.readFile(filePath, "utf-8");
29202
29508
  const errors = [];
29203
29509
  const result = jsonc2.parse(content, errors);
29204
29510
  return errors.length > 0 ? null : result;
@@ -29212,8 +29518,8 @@ async function readJsonFile(filePath) {
29212
29518
  __name(readJsonFile, "readJsonFile");
29213
29519
  async function writeJsonFile(filePath, data) {
29214
29520
  try {
29215
- await fs8.mkdir(path8.dirname(filePath), { recursive: true });
29216
- await fs8.writeFile(filePath, `${JSON.stringify(data, null, 2)}
29521
+ await fs9.mkdir(path8.dirname(filePath), { recursive: true });
29522
+ await fs9.writeFile(filePath, `${JSON.stringify(data, null, 2)}
29217
29523
  `, "utf-8");
29218
29524
  return true;
29219
29525
  } catch (error) {
@@ -29303,7 +29609,7 @@ function createRoutes(projectId, _projectPath) {
29303
29609
  }
29304
29610
  try {
29305
29611
  const filePath = path8.join(dataPath, "context", `${name}.md`);
29306
- const content = await fs8.readFile(filePath, "utf-8");
29612
+ const content = await fs9.readFile(filePath, "utf-8");
29307
29613
  return c.text(content, 200, { "Content-Type": "text/markdown" });
29308
29614
  } catch (error) {
29309
29615
  if (!isNotFoundError(error)) {
@@ -29319,7 +29625,7 @@ __name(createRoutes, "createRoutes");
29319
29625
  // core/server/routes-extended.ts
29320
29626
  init_path_manager();
29321
29627
  init_fs();
29322
- import fs9 from "node:fs/promises";
29628
+ import fs10 from "node:fs/promises";
29323
29629
  import path9 from "node:path";
29324
29630
  import { Hono as Hono2 } from "hono";
29325
29631
  import * as jsonc3 from "jsonc-parser";
@@ -29327,7 +29633,7 @@ var GLOBAL_BASE = path_manager_default.getGlobalBasePath();
29327
29633
  var PROJECTS_DIR = path9.join(GLOBAL_BASE, "projects");
29328
29634
  async function readJsonFile2(filePath) {
29329
29635
  try {
29330
- const content = await fs9.readFile(filePath, "utf-8");
29636
+ const content = await fs10.readFile(filePath, "utf-8");
29331
29637
  const errors = [];
29332
29638
  const result = jsonc3.parse(content, errors);
29333
29639
  return errors.length > 0 ? null : result;
@@ -29341,8 +29647,8 @@ async function readJsonFile2(filePath) {
29341
29647
  __name(readJsonFile2, "readJsonFile");
29342
29648
  async function writeJsonFile2(filePath, data) {
29343
29649
  try {
29344
- await fs9.mkdir(path9.dirname(filePath), { recursive: true });
29345
- await fs9.writeFile(filePath, `${JSON.stringify(data, null, 2)}
29650
+ await fs10.mkdir(path9.dirname(filePath), { recursive: true });
29651
+ await fs10.writeFile(filePath, `${JSON.stringify(data, null, 2)}
29346
29652
  `, "utf-8");
29347
29653
  return true;
29348
29654
  } catch (error) {
@@ -29379,8 +29685,8 @@ function createExtendedRoutes() {
29379
29685
  const api = new Hono2();
29380
29686
  api.get("/projects", async (c) => {
29381
29687
  try {
29382
- await fs9.mkdir(PROJECTS_DIR, { recursive: true });
29383
- const entries = await fs9.readdir(PROJECTS_DIR, { withFileTypes: true });
29688
+ await fs10.mkdir(PROJECTS_DIR, { recursive: true });
29689
+ const entries = await fs10.readdir(PROJECTS_DIR, { withFileTypes: true });
29384
29690
  const projectIds = entries.filter((e) => e.isDirectory()).map((e) => e.name);
29385
29691
  const projects = await Promise.all(
29386
29692
  projectIds.map(async (id) => {
@@ -29639,8 +29945,8 @@ function createExtendedRoutes() {
29639
29945
  });
29640
29946
  api.get("/stats/global", async (c) => {
29641
29947
  try {
29642
- await fs9.mkdir(PROJECTS_DIR, { recursive: true });
29643
- const entries = await fs9.readdir(PROJECTS_DIR, { withFileTypes: true });
29948
+ await fs10.mkdir(PROJECTS_DIR, { recursive: true });
29949
+ const entries = await fs10.readdir(PROJECTS_DIR, { withFileTypes: true });
29644
29950
  const projectIds = entries.filter((e) => e.isDirectory()).map((e) => e.name);
29645
29951
  let totalTasks = 0;
29646
29952
  let totalIdeas = 0;
@@ -29674,8 +29980,8 @@ function createExtendedRoutes() {
29674
29980
  api.get("/status-bar/compact", async (c) => {
29675
29981
  try {
29676
29982
  const cwd = c.req.query("cwd");
29677
- await fs9.mkdir(PROJECTS_DIR, { recursive: true });
29678
- const entries = await fs9.readdir(PROJECTS_DIR, { withFileTypes: true });
29983
+ await fs10.mkdir(PROJECTS_DIR, { recursive: true });
29984
+ const entries = await fs10.readdir(PROJECTS_DIR, { withFileTypes: true });
29679
29985
  const projectIds = entries.filter((e) => e.isDirectory()).map((e) => e.name);
29680
29986
  let targetProjectId = null;
29681
29987
  if (cwd) {