prjct-cli 1.16.0 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,10 +16,10 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
16
16
  if (typeof require !== "undefined") return require.apply(this, arguments);
17
17
  throw Error('Dynamic require of "' + x + '" is not supported');
18
18
  });
19
- var __glob = (map) => (path70) => {
20
- var fn = map[path70];
19
+ var __glob = (map) => (path72) => {
20
+ var fn = map[path72];
21
21
  if (fn) return fn();
22
- throw new Error("Module not found in bundle: " + path70);
22
+ throw new Error("Module not found in bundle: " + path72);
23
23
  };
24
24
  var __esm = (fn, res) => function __init() {
25
25
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
@@ -4051,7 +4051,7 @@ var init_cache = __esm({
4051
4051
  import { Database } from "bun:sqlite";
4052
4052
  import fs15 from "node:fs";
4053
4053
  import path14 from "node:path";
4054
- var migrations, PrjctDatabase, prjctDb;
4054
+ var migrations, PrjctDatabase, prjctDb, database_default;
4055
4055
  var init_database = __esm({
4056
4056
  "core/storage/database.ts"() {
4057
4057
  "use strict";
@@ -4482,6 +4482,7 @@ var init_database = __esm({
4482
4482
  }
4483
4483
  };
4484
4484
  prjctDb = new PrjctDatabase();
4485
+ database_default = prjctDb;
4485
4486
  }
4486
4487
  });
4487
4488
 
@@ -6575,11 +6576,11 @@ async function runSignaturesTool(args2, projectPath) {
6575
6576
  }
6576
6577
  };
6577
6578
  }
6578
- const fs58 = await import("node:fs/promises");
6579
- const path70 = await import("node:path");
6580
- const fullPath = path70.isAbsolute(filePath) ? filePath : path70.join(projectPath, filePath);
6579
+ const fs60 = await import("node:fs/promises");
6580
+ const path72 = await import("node:path");
6581
+ const fullPath = path72.isAbsolute(filePath) ? filePath : path72.join(projectPath, filePath);
6581
6582
  try {
6582
- const stat = await fs58.stat(fullPath);
6583
+ const stat = await fs60.stat(fullPath);
6583
6584
  if (stat.isDirectory()) {
6584
6585
  const results = await extractDirectorySignatures(filePath, projectPath, {
6585
6586
  recursive: args2.includes("--recursive") || args2.includes("-r")
@@ -6646,11 +6647,11 @@ async function runSummaryTool(args2, projectPath) {
6646
6647
  }
6647
6648
  };
6648
6649
  }
6649
- const fs58 = await import("node:fs/promises");
6650
- const path70 = await import("node:path");
6651
- const fullPath = path70.isAbsolute(targetPath) ? targetPath : path70.join(projectPath, targetPath);
6650
+ const fs60 = await import("node:fs/promises");
6651
+ const path72 = await import("node:path");
6652
+ const fullPath = path72.isAbsolute(targetPath) ? targetPath : path72.join(projectPath, targetPath);
6652
6653
  try {
6653
- const stat = await fs58.stat(fullPath);
6654
+ const stat = await fs60.stat(fullPath);
6654
6655
  if (stat.isDirectory()) {
6655
6656
  const results = await summarizeDirectory(targetPath, projectPath, {
6656
6657
  recursive: args2.includes("--recursive") || args2.includes("-r")
@@ -21767,16 +21768,16 @@ var init_onboarding = __esm({
21767
21768
  * Detect project type from file system
21768
21769
  */
21769
21770
  async detectProjectType() {
21770
- const fs58 = await import("node:fs/promises");
21771
- const path70 = await import("node:path");
21771
+ const fs60 = await import("node:fs/promises");
21772
+ const path72 = await import("node:path");
21772
21773
  try {
21773
- const files = await fs58.readdir(this.projectPath);
21774
+ const files = await fs60.readdir(this.projectPath);
21774
21775
  if (files.includes("turbo.json") || files.includes("lerna.json") || files.includes("nx.json")) {
21775
21776
  return "monorepo";
21776
21777
  }
21777
21778
  if (files.includes("package.json")) {
21778
- const pkgPath = path70.join(this.projectPath, "package.json");
21779
- const pkgContent = await fs58.readFile(pkgPath, "utf-8");
21779
+ const pkgPath = path72.join(this.projectPath, "package.json");
21780
+ const pkgContent = await fs60.readFile(pkgPath, "utf-8");
21780
21781
  const pkg = JSON.parse(pkgContent);
21781
21782
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
21782
21783
  if (pkg.bin) return "cli-tool";
@@ -21812,32 +21813,32 @@ var init_onboarding = __esm({
21812
21813
  * Detect installed AI agents from config files
21813
21814
  */
21814
21815
  async detectInstalledAgents() {
21815
- const fs58 = await import("node:fs/promises");
21816
- const path70 = await import("node:path");
21816
+ const fs60 = await import("node:fs/promises");
21817
+ const path72 = await import("node:path");
21817
21818
  const os22 = await import("node:os");
21818
21819
  const agents = [];
21819
21820
  try {
21820
- await fs58.access(path70.join(os22.homedir(), ".claude"));
21821
+ await fs60.access(path72.join(os22.homedir(), ".claude"));
21821
21822
  agents.push("claude");
21822
21823
  } catch {
21823
21824
  }
21824
21825
  try {
21825
- await fs58.access(path70.join(this.projectPath, ".cursorrules"));
21826
+ await fs60.access(path72.join(this.projectPath, ".cursorrules"));
21826
21827
  agents.push("cursor");
21827
21828
  } catch {
21828
21829
  }
21829
21830
  try {
21830
- await fs58.access(path70.join(this.projectPath, ".windsurfrules"));
21831
+ await fs60.access(path72.join(this.projectPath, ".windsurfrules"));
21831
21832
  agents.push("windsurf");
21832
21833
  } catch {
21833
21834
  }
21834
21835
  try {
21835
- await fs58.access(path70.join(this.projectPath, ".github", "copilot-instructions.md"));
21836
+ await fs60.access(path72.join(this.projectPath, ".github", "copilot-instructions.md"));
21836
21837
  agents.push("copilot");
21837
21838
  } catch {
21838
21839
  }
21839
21840
  try {
21840
- await fs58.access(path70.join(os22.homedir(), ".gemini"));
21841
+ await fs60.access(path72.join(os22.homedir(), ".gemini"));
21841
21842
  agents.push("gemini");
21842
21843
  } catch {
21843
21844
  }
@@ -21847,17 +21848,17 @@ var init_onboarding = __esm({
21847
21848
  * Detect tech stack from project files
21848
21849
  */
21849
21850
  async detectStack() {
21850
- const fs58 = await import("node:fs/promises");
21851
- const path70 = await import("node:path");
21851
+ const fs60 = await import("node:fs/promises");
21852
+ const path72 = await import("node:path");
21852
21853
  const stack = {
21853
21854
  language: "Unknown",
21854
21855
  technologies: []
21855
21856
  };
21856
21857
  try {
21857
- const files = await fs58.readdir(this.projectPath);
21858
+ const files = await fs60.readdir(this.projectPath);
21858
21859
  if (files.includes("package.json")) {
21859
- const pkgPath = path70.join(this.projectPath, "package.json");
21860
- const pkgContent = await fs58.readFile(pkgPath, "utf-8");
21860
+ const pkgPath = path72.join(this.projectPath, "package.json");
21861
+ const pkgContent = await fs60.readFile(pkgPath, "utf-8");
21861
21862
  const pkg = JSON.parse(pkgContent);
21862
21863
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
21863
21864
  stack.language = deps.typescript ? "TypeScript" : "JavaScript";
@@ -24082,8 +24083,8 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
24082
24083
  const globalPath2 = path_manager_default.getGlobalProjectPath(projectId);
24083
24084
  const specsPath2 = path45.join(globalPath2, "planning", "specs");
24084
24085
  try {
24085
- const fs58 = await import("node:fs/promises");
24086
- const files = await fs58.readdir(specsPath2);
24086
+ const fs60 = await import("node:fs/promises");
24087
+ const files = await fs60.readdir(specsPath2);
24087
24088
  const specs = files.filter((f) => f.endsWith(".md") && f !== ".gitkeep");
24088
24089
  if (specs.length === 0) {
24089
24090
  output_default.warn("no specs yet");
@@ -25010,9 +25011,518 @@ var init_ai_tools = __esm({
25010
25011
  }
25011
25012
  });
25012
25013
 
25013
- // core/services/context-generator.ts
25014
+ // core/domain/bm25.ts
25014
25015
  import fs46 from "node:fs/promises";
25015
25016
  import path49 from "node:path";
25017
+ function splitIdentifier(identifier) {
25018
+ return identifier.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/[-_./]/g, " ").toLowerCase().split(/\s+/).filter((w) => w.length > 1);
25019
+ }
25020
+ function tokenizeFile(content, filePath) {
25021
+ const tokens = [];
25022
+ const pathParts = filePath.replace(/\.[^.]+$/, "").split(/[/\\]/).filter(Boolean);
25023
+ for (const part of pathParts) {
25024
+ tokens.push(...splitIdentifier(part));
25025
+ }
25026
+ const exportPatterns = [
25027
+ /export\s+(?:async\s+)?function\s+(\w+)/g,
25028
+ /export\s+class\s+(\w+)/g,
25029
+ /export\s+interface\s+(\w+)/g,
25030
+ /export\s+type\s+(\w+)/g,
25031
+ /export\s+(?:const|let|var)\s+(\w+)/g,
25032
+ /export\s+default\s+(?:class|function)\s+(\w+)/g
25033
+ ];
25034
+ for (const pattern of exportPatterns) {
25035
+ let match;
25036
+ while ((match = pattern.exec(content)) !== null) {
25037
+ if (match[1]) {
25038
+ tokens.push(...splitIdentifier(match[1]));
25039
+ }
25040
+ }
25041
+ }
25042
+ const declPatterns = [
25043
+ /(?:async\s+)?function\s+(\w+)/g,
25044
+ /class\s+(\w+)/g,
25045
+ /interface\s+(\w+)/g,
25046
+ /type\s+(\w+)\s*=/g
25047
+ ];
25048
+ for (const pattern of declPatterns) {
25049
+ let match;
25050
+ while ((match = pattern.exec(content)) !== null) {
25051
+ if (match[1]) {
25052
+ tokens.push(...splitIdentifier(match[1]));
25053
+ }
25054
+ }
25055
+ }
25056
+ const importPattern = /(?:from|import)\s+['"]([^'"]+)['"]/g;
25057
+ let importMatch;
25058
+ while ((importMatch = importPattern.exec(content)) !== null) {
25059
+ const source = importMatch[1];
25060
+ if (source.startsWith(".") || source.startsWith("@/")) {
25061
+ tokens.push(...splitIdentifier(source));
25062
+ } else {
25063
+ const pkgName = source.startsWith("@") ? source.split("/").slice(0, 2).join("/") : source.split("/")[0];
25064
+ tokens.push(...splitIdentifier(pkgName));
25065
+ }
25066
+ }
25067
+ const singleLineComments = /\/\/\s*(.+)/g;
25068
+ let commentMatch;
25069
+ while ((commentMatch = singleLineComments.exec(content)) !== null) {
25070
+ const words = commentMatch[1].toLowerCase().split(/\s+/).filter((w) => w.length > 2);
25071
+ tokens.push(...words);
25072
+ }
25073
+ const multiLineComments = /\/\*\*?([\s\S]*?)\*\//g;
25074
+ let multiMatch;
25075
+ while ((multiMatch = multiLineComments.exec(content)) !== null) {
25076
+ const words = multiMatch[1].replace(/@\w+/g, "").replace(/\*/g, "").toLowerCase().split(/\s+/).filter((w) => w.length > 2 && /^[a-z]+$/.test(w));
25077
+ tokens.push(...words);
25078
+ }
25079
+ return tokens.filter((t) => t.length > 1 && !STOP_WORDS.has(t) && /^[a-z][a-z0-9]*$/.test(t));
25080
+ }
25081
+ async function listFiles2(dir, projectPath) {
25082
+ const files = [];
25083
+ const entries = await fs46.readdir(dir, { withFileTypes: true });
25084
+ for (const entry of entries) {
25085
+ if (SKIP_DIRS.has(entry.name)) continue;
25086
+ const fullPath = path49.join(dir, entry.name);
25087
+ if (entry.isDirectory()) {
25088
+ files.push(...await listFiles2(fullPath, projectPath));
25089
+ } else if (entry.isFile()) {
25090
+ const ext = path49.extname(entry.name).toLowerCase();
25091
+ if (INDEXABLE_EXTENSIONS.has(ext)) {
25092
+ files.push(path49.relative(projectPath, fullPath));
25093
+ }
25094
+ }
25095
+ }
25096
+ return files;
25097
+ }
25098
+ async function buildIndex(projectPath) {
25099
+ const files = await listFiles2(projectPath, projectPath);
25100
+ const documents = {};
25101
+ const invertedIndex = {};
25102
+ let totalLength = 0;
25103
+ const BATCH_SIZE = 50;
25104
+ for (let i = 0; i < files.length; i += BATCH_SIZE) {
25105
+ const batch = files.slice(i, i + BATCH_SIZE);
25106
+ const results = await Promise.all(
25107
+ batch.map(async (filePath) => {
25108
+ try {
25109
+ const content = await fs46.readFile(path49.join(projectPath, filePath), "utf-8");
25110
+ const tokens = tokenizeFile(content, filePath);
25111
+ return { filePath, tokens };
25112
+ } catch {
25113
+ return { filePath, tokens: [] };
25114
+ }
25115
+ })
25116
+ );
25117
+ for (const { filePath, tokens } of results) {
25118
+ if (tokens.length === 0) continue;
25119
+ documents[filePath] = { tokens, length: tokens.length };
25120
+ totalLength += tokens.length;
25121
+ const tfMap = /* @__PURE__ */ new Map();
25122
+ for (const token of tokens) {
25123
+ tfMap.set(token, (tfMap.get(token) || 0) + 1);
25124
+ }
25125
+ for (const [token, tf] of tfMap) {
25126
+ if (!invertedIndex[token]) {
25127
+ invertedIndex[token] = [];
25128
+ }
25129
+ invertedIndex[token].push({ path: filePath, tf });
25130
+ }
25131
+ }
25132
+ }
25133
+ const totalDocs = Object.keys(documents).length;
25134
+ return {
25135
+ documents,
25136
+ invertedIndex,
25137
+ avgDocLength: totalDocs > 0 ? totalLength / totalDocs : 0,
25138
+ totalDocs,
25139
+ builtAt: (/* @__PURE__ */ new Date()).toISOString()
25140
+ };
25141
+ }
25142
+ function saveIndex(projectId, index) {
25143
+ const storable = {
25144
+ invertedIndex: index.invertedIndex,
25145
+ avgDocLength: index.avgDocLength,
25146
+ totalDocs: index.totalDocs,
25147
+ builtAt: index.builtAt,
25148
+ // Store document lengths (needed for scoring) but not full token lists
25149
+ docLengths: Object.fromEntries(Object.entries(index.documents).map(([p, d]) => [p, d.length]))
25150
+ };
25151
+ database_default.setDoc(projectId, INDEX_KEY, storable);
25152
+ }
25153
+ async function indexProject(projectPath, projectId) {
25154
+ const index = await buildIndex(projectPath);
25155
+ saveIndex(projectId, index);
25156
+ return index;
25157
+ }
25158
+ var INDEXABLE_EXTENSIONS, STOP_WORDS, SKIP_DIRS, INDEX_KEY;
25159
+ var init_bm25 = __esm({
25160
+ "core/domain/bm25.ts"() {
25161
+ "use strict";
25162
+ init_database();
25163
+ INDEXABLE_EXTENSIONS = /* @__PURE__ */ new Set([
25164
+ ".ts",
25165
+ ".tsx",
25166
+ ".js",
25167
+ ".jsx",
25168
+ ".mjs",
25169
+ ".cjs",
25170
+ ".py",
25171
+ ".go",
25172
+ ".rs",
25173
+ ".java",
25174
+ ".cs",
25175
+ ".rb",
25176
+ ".php",
25177
+ ".vue",
25178
+ ".svelte"
25179
+ ]);
25180
+ STOP_WORDS = /* @__PURE__ */ new Set([
25181
+ "the",
25182
+ "a",
25183
+ "an",
25184
+ "is",
25185
+ "are",
25186
+ "was",
25187
+ "were",
25188
+ "be",
25189
+ "been",
25190
+ "being",
25191
+ "have",
25192
+ "has",
25193
+ "had",
25194
+ "do",
25195
+ "does",
25196
+ "did",
25197
+ "will",
25198
+ "would",
25199
+ "could",
25200
+ "should",
25201
+ "may",
25202
+ "might",
25203
+ "shall",
25204
+ "can",
25205
+ "of",
25206
+ "in",
25207
+ "to",
25208
+ "for",
25209
+ "with",
25210
+ "on",
25211
+ "at",
25212
+ "from",
25213
+ "by",
25214
+ "as",
25215
+ "or",
25216
+ "and",
25217
+ "but",
25218
+ "if",
25219
+ "not",
25220
+ "no",
25221
+ "so",
25222
+ "up",
25223
+ "out",
25224
+ "this",
25225
+ "that",
25226
+ "it",
25227
+ "its",
25228
+ "all",
25229
+ "any",
25230
+ // Code noise
25231
+ "import",
25232
+ "export",
25233
+ "default",
25234
+ "const",
25235
+ "let",
25236
+ "var",
25237
+ "function",
25238
+ "class",
25239
+ "interface",
25240
+ "type",
25241
+ "return",
25242
+ "new",
25243
+ "true",
25244
+ "false",
25245
+ "null",
25246
+ "undefined",
25247
+ "void",
25248
+ "async",
25249
+ "await",
25250
+ "static",
25251
+ "public",
25252
+ "private",
25253
+ "protected",
25254
+ "readonly",
25255
+ "string",
25256
+ "number",
25257
+ "boolean",
25258
+ "object",
25259
+ "array"
25260
+ ]);
25261
+ SKIP_DIRS = /* @__PURE__ */ new Set([
25262
+ "node_modules",
25263
+ ".git",
25264
+ "dist",
25265
+ "build",
25266
+ "out",
25267
+ ".next",
25268
+ "coverage",
25269
+ ".cache",
25270
+ ".turbo",
25271
+ ".vercel",
25272
+ "__pycache__",
25273
+ "vendor",
25274
+ "target"
25275
+ ]);
25276
+ __name(splitIdentifier, "splitIdentifier");
25277
+ __name(tokenizeFile, "tokenizeFile");
25278
+ __name(listFiles2, "listFiles");
25279
+ __name(buildIndex, "buildIndex");
25280
+ INDEX_KEY = "bm25-index";
25281
+ __name(saveIndex, "saveIndex");
25282
+ __name(indexProject, "indexProject");
25283
+ }
25284
+ });
25285
+
25286
+ // core/domain/git-cochange.ts
25287
+ import { exec as execCallback7 } from "node:child_process";
25288
+ import { promisify as promisify15 } from "node:util";
25289
+ async function parseGitLog(projectPath, maxCommits = 100) {
25290
+ try {
25291
+ const { stdout } = await exec14(
25292
+ `git log --name-only --pretty=format:'---COMMIT---' -${maxCommits}`,
25293
+ { cwd: projectPath, maxBuffer: 10 * 1024 * 1024 }
25294
+ );
25295
+ const commits = [];
25296
+ let currentFiles = null;
25297
+ for (const line of stdout.split("\n")) {
25298
+ const trimmed = line.trim();
25299
+ if (trimmed === "---COMMIT---") {
25300
+ if (currentFiles && currentFiles.size > 0 && currentFiles.size <= MAX_FILES_PER_COMMIT) {
25301
+ commits.push(currentFiles);
25302
+ }
25303
+ currentFiles = /* @__PURE__ */ new Set();
25304
+ } else if (trimmed && currentFiles) {
25305
+ if (isSourceFile(trimmed)) {
25306
+ currentFiles.add(trimmed);
25307
+ }
25308
+ }
25309
+ }
25310
+ if (currentFiles && currentFiles.size > 0 && currentFiles.size <= MAX_FILES_PER_COMMIT) {
25311
+ commits.push(currentFiles);
25312
+ }
25313
+ return commits;
25314
+ } catch {
25315
+ return [];
25316
+ }
25317
+ }
25318
+ function isSourceFile(filePath) {
25319
+ const sourceExtensions = /\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|cs|rb|php|vue|svelte)$/i;
25320
+ return sourceExtensions.test(filePath) && !filePath.includes("node_modules/");
25321
+ }
25322
+ async function buildMatrix(projectPath, maxCommits = 100) {
25323
+ const commitSets = await parseGitLog(projectPath, maxCommits);
25324
+ const fileCommitCount = /* @__PURE__ */ new Map();
25325
+ const pairCount = /* @__PURE__ */ new Map();
25326
+ for (const files of commitSets) {
25327
+ const fileArray = Array.from(files);
25328
+ for (const file of fileArray) {
25329
+ fileCommitCount.set(file, (fileCommitCount.get(file) || 0) + 1);
25330
+ }
25331
+ for (let i = 0; i < fileArray.length; i++) {
25332
+ for (let j = i + 1; j < fileArray.length; j++) {
25333
+ const key = pairKey(fileArray[i], fileArray[j]);
25334
+ pairCount.set(key, (pairCount.get(key) || 0) + 1);
25335
+ }
25336
+ }
25337
+ }
25338
+ const matrix = {};
25339
+ for (const [key, count] of pairCount) {
25340
+ const [fileA, fileB] = key.split("\0");
25341
+ const countA = fileCommitCount.get(fileA) || 0;
25342
+ const countB = fileCommitCount.get(fileB) || 0;
25343
+ if (countA < MIN_FILE_OCCURRENCES || countB < MIN_FILE_OCCURRENCES) continue;
25344
+ const unionCount = countA + countB - count;
25345
+ const similarity = unionCount > 0 ? count / unionCount : 0;
25346
+ if (similarity < MIN_SIMILARITY) continue;
25347
+ if (!matrix[fileA]) matrix[fileA] = {};
25348
+ if (!matrix[fileB]) matrix[fileB] = {};
25349
+ matrix[fileA][fileB] = similarity;
25350
+ matrix[fileB][fileA] = similarity;
25351
+ }
25352
+ return {
25353
+ matrix,
25354
+ commitsAnalyzed: commitSets.length,
25355
+ filesAnalyzed: fileCommitCount.size,
25356
+ builtAt: (/* @__PURE__ */ new Date()).toISOString()
25357
+ };
25358
+ }
25359
+ function pairKey(a, b) {
25360
+ return a < b ? `${a}\0${b}` : `${b}\0${a}`;
25361
+ }
25362
+ function saveMatrix(projectId, index) {
25363
+ database_default.setDoc(projectId, INDEX_KEY2, index);
25364
+ }
25365
+ async function indexCoChanges(projectPath, projectId, maxCommits = 100) {
25366
+ const index = await buildMatrix(projectPath, maxCommits);
25367
+ saveMatrix(projectId, index);
25368
+ return index;
25369
+ }
25370
+ var exec14, MIN_SIMILARITY, MIN_FILE_OCCURRENCES, MAX_FILES_PER_COMMIT, INDEX_KEY2;
25371
+ var init_git_cochange = __esm({
25372
+ "core/domain/git-cochange.ts"() {
25373
+ "use strict";
25374
+ init_database();
25375
+ exec14 = promisify15(execCallback7);
25376
+ MIN_SIMILARITY = 0.1;
25377
+ MIN_FILE_OCCURRENCES = 2;
25378
+ MAX_FILES_PER_COMMIT = 30;
25379
+ __name(parseGitLog, "parseGitLog");
25380
+ __name(isSourceFile, "isSourceFile");
25381
+ __name(buildMatrix, "buildMatrix");
25382
+ __name(pairKey, "pairKey");
25383
+ INDEX_KEY2 = "cochange-index";
25384
+ __name(saveMatrix, "saveMatrix");
25385
+ __name(indexCoChanges, "indexCoChanges");
25386
+ }
25387
+ });
25388
+
25389
+ // core/domain/import-graph.ts
25390
+ import fs47 from "node:fs/promises";
25391
+ import path50 from "node:path";
25392
+ function extractImportSources(content) {
25393
+ const sources = [];
25394
+ let match;
25395
+ const regex = new RegExp(IMPORT_REGEX.source, "g");
25396
+ while ((match = regex.exec(content)) !== null) {
25397
+ const source = match[1];
25398
+ if (source.startsWith(".") || source.startsWith("@/")) {
25399
+ sources.push(source);
25400
+ }
25401
+ }
25402
+ return sources;
25403
+ }
25404
+ async function resolveImport2(source, fromFile, projectPath) {
25405
+ let basePath;
25406
+ if (source.startsWith("@/")) {
25407
+ basePath = path50.join(projectPath, "src", source.slice(2));
25408
+ } else {
25409
+ const fromDir = path50.dirname(path50.join(projectPath, fromFile));
25410
+ basePath = path50.resolve(fromDir, source);
25411
+ }
25412
+ for (const ext of RESOLVE_EXTENSIONS) {
25413
+ const fullPath = basePath + ext;
25414
+ try {
25415
+ const stat = await fs47.stat(fullPath);
25416
+ if (stat.isFile()) {
25417
+ return path50.relative(projectPath, fullPath);
25418
+ }
25419
+ } catch {
25420
+ }
25421
+ }
25422
+ return null;
25423
+ }
25424
+ async function listFiles3(dir, projectPath) {
25425
+ const files = [];
25426
+ const entries = await fs47.readdir(dir, { withFileTypes: true });
25427
+ for (const entry of entries) {
25428
+ if (SKIP_DIRS2.has(entry.name)) continue;
25429
+ const fullPath = path50.join(dir, entry.name);
25430
+ if (entry.isDirectory()) {
25431
+ files.push(...await listFiles3(fullPath, projectPath));
25432
+ } else if (entry.isFile()) {
25433
+ const ext = path50.extname(entry.name).toLowerCase();
25434
+ if (INDEXABLE_EXTENSIONS2.has(ext)) {
25435
+ files.push(path50.relative(projectPath, fullPath));
25436
+ }
25437
+ }
25438
+ }
25439
+ return files;
25440
+ }
25441
+ async function buildGraph(projectPath) {
25442
+ const files = await listFiles3(projectPath, projectPath);
25443
+ const forward = {};
25444
+ const reverse = {};
25445
+ let edgeCount = 0;
25446
+ const BATCH_SIZE = 50;
25447
+ for (let i = 0; i < files.length; i += BATCH_SIZE) {
25448
+ const batch = files.slice(i, i + BATCH_SIZE);
25449
+ const results = await Promise.all(
25450
+ batch.map(async (filePath) => {
25451
+ try {
25452
+ const content = await fs47.readFile(path50.join(projectPath, filePath), "utf-8");
25453
+ const sources = extractImportSources(content);
25454
+ const resolved = [];
25455
+ for (const source of sources) {
25456
+ const target = await resolveImport2(source, filePath, projectPath);
25457
+ if (target && target !== filePath) {
25458
+ resolved.push(target);
25459
+ }
25460
+ }
25461
+ return { filePath, imports: resolved };
25462
+ } catch {
25463
+ return { filePath, imports: [] };
25464
+ }
25465
+ })
25466
+ );
25467
+ for (const { filePath, imports } of results) {
25468
+ if (imports.length === 0) continue;
25469
+ forward[filePath] = imports;
25470
+ edgeCount += imports.length;
25471
+ for (const target of imports) {
25472
+ if (!reverse[target]) reverse[target] = [];
25473
+ reverse[target].push(filePath);
25474
+ }
25475
+ }
25476
+ }
25477
+ return {
25478
+ forward,
25479
+ reverse,
25480
+ fileCount: files.length,
25481
+ edgeCount,
25482
+ builtAt: (/* @__PURE__ */ new Date()).toISOString()
25483
+ };
25484
+ }
25485
+ function saveGraph(projectId, graph) {
25486
+ database_default.setDoc(projectId, INDEX_KEY3, graph);
25487
+ }
25488
+ async function indexImports(projectPath, projectId) {
25489
+ const graph = await buildGraph(projectPath);
25490
+ saveGraph(projectId, graph);
25491
+ return graph;
25492
+ }
25493
+ var INDEXABLE_EXTENSIONS2, SKIP_DIRS2, RESOLVE_EXTENSIONS, IMPORT_REGEX, INDEX_KEY3;
25494
+ var init_import_graph = __esm({
25495
+ "core/domain/import-graph.ts"() {
25496
+ "use strict";
25497
+ init_database();
25498
+ INDEXABLE_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
25499
+ SKIP_DIRS2 = /* @__PURE__ */ new Set([
25500
+ "node_modules",
25501
+ ".git",
25502
+ "dist",
25503
+ "build",
25504
+ "out",
25505
+ ".next",
25506
+ "coverage",
25507
+ ".cache",
25508
+ ".turbo",
25509
+ ".vercel"
25510
+ ]);
25511
+ RESOLVE_EXTENSIONS = ["", ".ts", ".tsx", ".js", ".jsx", "/index.ts", "/index.js"];
25512
+ IMPORT_REGEX = /(?:import|from)\s+['"]([^'"]+)['"]/g;
25513
+ __name(extractImportSources, "extractImportSources");
25514
+ __name(resolveImport2, "resolveImport");
25515
+ __name(listFiles3, "listFiles");
25516
+ __name(buildGraph, "buildGraph");
25517
+ INDEX_KEY3 = "import-graph";
25518
+ __name(saveGraph, "saveGraph");
25519
+ __name(indexImports, "indexImports");
25520
+ }
25521
+ });
25522
+
25523
+ // core/services/context-generator.ts
25524
+ import fs48 from "node:fs/promises";
25525
+ import path51 from "node:path";
25016
25526
  var ContextFileGenerator;
25017
25527
  var init_context_generator = __esm({
25018
25528
  "core/services/context-generator.ts"() {
@@ -25037,10 +25547,10 @@ var init_context_generator = __esm({
25037
25547
  async writeWithPreservation(filePath, content) {
25038
25548
  let finalContent = content;
25039
25549
  try {
25040
- const existingContent = await fs46.readFile(filePath, "utf-8");
25550
+ const existingContent = await fs48.readFile(filePath, "utf-8");
25041
25551
  const validation = validatePreserveBlocks(existingContent);
25042
25552
  if (!validation.valid) {
25043
- const filename = path49.basename(filePath);
25553
+ const filename = path51.basename(filePath);
25044
25554
  console.warn(`\u26A0\uFE0F ${filename} has invalid preserve blocks:`);
25045
25555
  for (const error of validation.errors) {
25046
25556
  console.warn(` ${error}`);
@@ -25049,13 +25559,13 @@ var init_context_generator = __esm({
25049
25559
  finalContent = mergePreservedSections(content, existingContent);
25050
25560
  } catch {
25051
25561
  }
25052
- await fs46.writeFile(filePath, finalContent, "utf-8");
25562
+ await fs48.writeFile(filePath, finalContent, "utf-8");
25053
25563
  }
25054
25564
  /**
25055
25565
  * Generate all context files in parallel
25056
25566
  */
25057
25567
  async generate(git, stats, commands, agents, sources) {
25058
- const contextPath = path49.join(this.config.globalPath, "context");
25568
+ const contextPath = path51.join(this.config.globalPath, "context");
25059
25569
  await Promise.all([
25060
25570
  this.generateClaudeMd(contextPath, git, stats, commands, agents, sources),
25061
25571
  this.generateNowMd(contextPath),
@@ -25155,7 +25665,7 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
25155
25665
  **Workflow**: ${workflowAgents.join(", ")}
25156
25666
  **Domain**: ${domainAgents.join(", ") || "none"}
25157
25667
  `;
25158
- const claudePath = path49.join(contextPath, "CLAUDE.md");
25668
+ const claudePath = path51.join(contextPath, "CLAUDE.md");
25159
25669
  await this.writeWithPreservation(claudePath, content);
25160
25670
  }
25161
25671
  /**
@@ -25164,8 +25674,8 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
25164
25674
  async generateNowMd(contextPath) {
25165
25675
  let currentTask = null;
25166
25676
  try {
25167
- const statePath = path49.join(this.config.globalPath, "storage", "state.json");
25168
- const state = JSON.parse(await fs46.readFile(statePath, "utf-8"));
25677
+ const statePath = path51.join(this.config.globalPath, "storage", "state.json");
25678
+ const state = JSON.parse(await fs48.readFile(statePath, "utf-8"));
25169
25679
  currentTask = state.currentTask;
25170
25680
  } catch {
25171
25681
  }
@@ -25181,7 +25691,7 @@ _No active task_
25181
25691
 
25182
25692
  Use \`p. task "description"\` to start working.
25183
25693
  `;
25184
- await this.writeWithPreservation(path49.join(contextPath, "now.md"), content);
25694
+ await this.writeWithPreservation(path51.join(contextPath, "now.md"), content);
25185
25695
  }
25186
25696
  /**
25187
25697
  * Generate next.md - task queue
@@ -25189,15 +25699,15 @@ Use \`p. task "description"\` to start working.
25189
25699
  async generateNextMd(contextPath) {
25190
25700
  let queue = { tasks: [] };
25191
25701
  try {
25192
- const queuePath = path49.join(this.config.globalPath, "storage", "queue.json");
25193
- queue = JSON.parse(await fs46.readFile(queuePath, "utf-8"));
25702
+ const queuePath = path51.join(this.config.globalPath, "storage", "queue.json");
25703
+ queue = JSON.parse(await fs48.readFile(queuePath, "utf-8"));
25194
25704
  } catch {
25195
25705
  }
25196
25706
  const content = `# NEXT
25197
25707
 
25198
25708
  ${queue.tasks.length > 0 ? queue.tasks.map((t, i) => `${i + 1}. ${t.description}${t.priority ? ` [${t.priority}]` : ""}`).join("\n") : "_Empty queue_"}
25199
25709
  `;
25200
- await this.writeWithPreservation(path49.join(contextPath, "next.md"), content);
25710
+ await this.writeWithPreservation(path51.join(contextPath, "next.md"), content);
25201
25711
  }
25202
25712
  /**
25203
25713
  * Generate ideas.md - captured ideas
@@ -25205,15 +25715,15 @@ ${queue.tasks.length > 0 ? queue.tasks.map((t, i) => `${i + 1}. ${t.description}
25205
25715
  async generateIdeasMd(contextPath) {
25206
25716
  let ideas = { ideas: [] };
25207
25717
  try {
25208
- const ideasPath = path49.join(this.config.globalPath, "storage", "ideas.json");
25209
- ideas = JSON.parse(await fs46.readFile(ideasPath, "utf-8"));
25718
+ const ideasPath = path51.join(this.config.globalPath, "storage", "ideas.json");
25719
+ ideas = JSON.parse(await fs48.readFile(ideasPath, "utf-8"));
25210
25720
  } catch {
25211
25721
  }
25212
25722
  const content = `# IDEAS
25213
25723
 
25214
25724
  ${ideas.ideas.length > 0 ? ideas.ideas.map((i) => `- ${i.text}${i.priority ? ` [${i.priority}]` : ""}`).join("\n") : "_No ideas captured yet_"}
25215
25725
  `;
25216
- await this.writeWithPreservation(path49.join(contextPath, "ideas.md"), content);
25726
+ await this.writeWithPreservation(path51.join(contextPath, "ideas.md"), content);
25217
25727
  }
25218
25728
  /**
25219
25729
  * Generate shipped.md - completed features
@@ -25223,8 +25733,8 @@ ${ideas.ideas.length > 0 ? ideas.ideas.map((i) => `- ${i.text}${i.priority ? ` [
25223
25733
  shipped: []
25224
25734
  };
25225
25735
  try {
25226
- const shippedPath = path49.join(this.config.globalPath, "storage", "shipped.json");
25227
- shipped = JSON.parse(await fs46.readFile(shippedPath, "utf-8"));
25736
+ const shippedPath = path51.join(this.config.globalPath, "storage", "shipped.json");
25737
+ shipped = JSON.parse(await fs48.readFile(shippedPath, "utf-8"));
25228
25738
  } catch {
25229
25739
  }
25230
25740
  const content = `# SHIPPED \u{1F680}
@@ -25233,7 +25743,7 @@ ${shipped.shipped.length > 0 ? shipped.shipped.slice(-10).map((s) => `- **${s.na
25233
25743
 
25234
25744
  **Total shipped:** ${shipped.shipped.length}
25235
25745
  `;
25236
- await this.writeWithPreservation(path49.join(contextPath, "shipped.md"), content);
25746
+ await this.writeWithPreservation(path51.join(contextPath, "shipped.md"), content);
25237
25747
  }
25238
25748
  // ==========================================================================
25239
25749
  // MONOREPO SUPPORT
@@ -25262,9 +25772,9 @@ ${shipped.shipped.length > 0 ? shipped.shipped.slice(-10).map((s) => `- **${s.na
25262
25772
  commands,
25263
25773
  agents
25264
25774
  );
25265
- const claudePath = path49.join(pkg.path, "CLAUDE.md");
25775
+ const claudePath = path51.join(pkg.path, "CLAUDE.md");
25266
25776
  await this.writeWithPreservation(claudePath, content);
25267
- generatedFiles.push(path49.relative(this.config.projectPath, claudePath));
25777
+ generatedFiles.push(path51.relative(this.config.projectPath, claudePath));
25268
25778
  }
25269
25779
  return generatedFiles;
25270
25780
  }
@@ -25277,8 +25787,8 @@ ${shipped.shipped.length > 0 ? shipped.shipped.slice(-10).map((s) => `- **${s.na
25277
25787
  let pkgVersion = stats.version;
25278
25788
  let pkgName = pkg.name;
25279
25789
  try {
25280
- const pkgJsonPath = path49.join(pkg.path, "package.json");
25281
- const pkgJson = JSON.parse(await fs46.readFile(pkgJsonPath, "utf-8"));
25790
+ const pkgJsonPath = path51.join(pkg.path, "package.json");
25791
+ const pkgJson = JSON.parse(await fs48.readFile(pkgJsonPath, "utf-8"));
25282
25792
  pkgVersion = pkgJson.version || stats.version;
25283
25793
  pkgName = pkgJson.name || pkg.name;
25284
25794
  } catch {
@@ -25343,8 +25853,8 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
25343
25853
  });
25344
25854
 
25345
25855
  // core/services/local-state-generator.ts
25346
- import fs47 from "node:fs/promises";
25347
- import path50 from "node:path";
25856
+ import fs49 from "node:fs/promises";
25857
+ import path52 from "node:path";
25348
25858
  var LOCAL_STATE_FILENAME, LocalStateGenerator, localStateGenerator;
25349
25859
  var init_local_state_generator = __esm({
25350
25860
  "core/services/local-state-generator.ts"() {
@@ -25359,17 +25869,17 @@ var init_local_state_generator = __esm({
25359
25869
  * Generate .prjct-state.md in the project root
25360
25870
  */
25361
25871
  async generate(projectPath, state) {
25362
- const filePath = path50.join(projectPath, LOCAL_STATE_FILENAME);
25872
+ const filePath = path52.join(projectPath, LOCAL_STATE_FILENAME);
25363
25873
  const content = this.toMarkdown(state);
25364
- await fs47.writeFile(filePath, content, "utf-8");
25874
+ await fs49.writeFile(filePath, content, "utf-8");
25365
25875
  }
25366
25876
  /**
25367
25877
  * Remove local state file
25368
25878
  */
25369
25879
  async remove(projectPath) {
25370
- const filePath = path50.join(projectPath, LOCAL_STATE_FILENAME);
25880
+ const filePath = path52.join(projectPath, LOCAL_STATE_FILENAME);
25371
25881
  try {
25372
- await fs47.unlink(filePath);
25882
+ await fs49.unlink(filePath);
25373
25883
  } catch (error) {
25374
25884
  if (!isNotFoundError(error)) throw error;
25375
25885
  }
@@ -25378,9 +25888,9 @@ var init_local_state_generator = __esm({
25378
25888
  * Check if local state file exists
25379
25889
  */
25380
25890
  async exists(projectPath) {
25381
- const filePath = path50.join(projectPath, LOCAL_STATE_FILENAME);
25891
+ const filePath = path52.join(projectPath, LOCAL_STATE_FILENAME);
25382
25892
  try {
25383
- await fs47.access(filePath);
25893
+ await fs49.access(filePath);
25384
25894
  return true;
25385
25895
  } catch {
25386
25896
  return false;
@@ -25459,11 +25969,11 @@ var init_local_state_generator = __esm({
25459
25969
  });
25460
25970
 
25461
25971
  // core/services/skill-lock.ts
25462
- import fs48 from "node:fs/promises";
25972
+ import fs50 from "node:fs/promises";
25463
25973
  import os14 from "node:os";
25464
- import path51 from "node:path";
25974
+ import path53 from "node:path";
25465
25975
  function getLockFilePath() {
25466
- return path51.join(os14.homedir(), ".prjct-cli", "skills", LOCK_FILE_NAME);
25976
+ return path53.join(os14.homedir(), ".prjct-cli", "skills", LOCK_FILE_NAME);
25467
25977
  }
25468
25978
  function createEmptyLockFile() {
25469
25979
  return {
@@ -25474,7 +25984,7 @@ function createEmptyLockFile() {
25474
25984
  }
25475
25985
  async function read() {
25476
25986
  try {
25477
- const content = await fs48.readFile(getLockFilePath(), "utf-8");
25987
+ const content = await fs50.readFile(getLockFilePath(), "utf-8");
25478
25988
  return JSON.parse(content);
25479
25989
  } catch {
25480
25990
  return createEmptyLockFile();
@@ -25482,9 +25992,9 @@ async function read() {
25482
25992
  }
25483
25993
  async function write(lockFile) {
25484
25994
  const lockPath = getLockFilePath();
25485
- await fs48.mkdir(path51.dirname(lockPath), { recursive: true });
25995
+ await fs50.mkdir(path53.dirname(lockPath), { recursive: true });
25486
25996
  lockFile.generatedAt = (/* @__PURE__ */ new Date()).toISOString();
25487
- await fs48.writeFile(lockPath, JSON.stringify(lockFile, null, 2), "utf-8");
25997
+ await fs50.writeFile(lockPath, JSON.stringify(lockFile, null, 2), "utf-8");
25488
25998
  }
25489
25999
  async function addEntry(entry) {
25490
26000
  const lockFile = await read();
@@ -25536,15 +26046,15 @@ var init_skill_lock = __esm({
25536
26046
  });
25537
26047
 
25538
26048
  // core/services/skill-installer.ts
25539
- import { exec as execCallback7 } from "node:child_process";
25540
- import fs49 from "node:fs/promises";
26049
+ import { exec as execCallback8 } from "node:child_process";
26050
+ import fs51 from "node:fs/promises";
25541
26051
  import os15 from "node:os";
25542
- import path52 from "node:path";
25543
- import { promisify as promisify15 } from "node:util";
26052
+ import path54 from "node:path";
26053
+ import { promisify as promisify16 } from "node:util";
25544
26054
  import { glob } from "glob";
25545
26055
  function parseSource(source) {
25546
26056
  if (source.startsWith("./") || source.startsWith("/") || source.startsWith("~")) {
25547
- const resolvedPath = source.startsWith("~") ? path52.join(os15.homedir(), source.slice(1)) : path52.resolve(source);
26057
+ const resolvedPath = source.startsWith("~") ? path54.join(os15.homedir(), source.slice(1)) : path54.resolve(source);
25548
26058
  return {
25549
26059
  type: "local",
25550
26060
  localPath: resolvedPath,
@@ -25582,22 +26092,22 @@ function parseSource(source) {
25582
26092
  async function discoverSkills(dir) {
25583
26093
  const skills = [];
25584
26094
  try {
25585
- const rootSkill = path52.join(dir, "SKILL.md");
25586
- await fs49.access(rootSkill);
25587
- const dirName = path52.basename(dir);
26095
+ const rootSkill = path54.join(dir, "SKILL.md");
26096
+ await fs51.access(rootSkill);
26097
+ const dirName = path54.basename(dir);
25588
26098
  skills.push({ name: dirName, filePath: rootSkill });
25589
26099
  } catch {
25590
26100
  }
25591
26101
  const subdirSkills = await glob("*/SKILL.md", { cwd: dir, absolute: true });
25592
26102
  for (const filePath of subdirSkills) {
25593
- const name = path52.basename(path52.dirname(filePath));
26103
+ const name = path54.basename(path54.dirname(filePath));
25594
26104
  if (!skills.some((s) => s.name === name)) {
25595
26105
  skills.push({ name, filePath });
25596
26106
  }
25597
26107
  }
25598
26108
  const nestedSkills = await glob("skills/*/SKILL.md", { cwd: dir, absolute: true });
25599
26109
  for (const filePath of nestedSkills) {
25600
- const name = path52.basename(path52.dirname(filePath));
26110
+ const name = path54.basename(path54.dirname(filePath));
25601
26111
  if (!skills.some((s) => s.name === name)) {
25602
26112
  skills.push({ name, filePath });
25603
26113
  }
@@ -25633,16 +26143,16 @@ ${prjctBlock.join("\n")}
25633
26143
  ${content}`;
25634
26144
  }
25635
26145
  function getInstallDir() {
25636
- return path52.join(os15.homedir(), ".claude", "skills");
26146
+ return path54.join(os15.homedir(), ".claude", "skills");
25637
26147
  }
25638
26148
  async function installSkillFile(sourcePath, name, source, sha) {
25639
26149
  const installDir = getInstallDir();
25640
- const targetDir = path52.join(installDir, name);
25641
- const targetPath = path52.join(targetDir, "SKILL.md");
25642
- const content = await fs49.readFile(sourcePath, "utf-8");
26150
+ const targetDir = path54.join(installDir, name);
26151
+ const targetPath = path54.join(targetDir, "SKILL.md");
26152
+ const content = await fs51.readFile(sourcePath, "utf-8");
25643
26153
  const enrichedContent = injectSourceMetadata(content, source, sha);
25644
- await fs49.mkdir(targetDir, { recursive: true });
25645
- await fs49.writeFile(targetPath, enrichedContent, "utf-8");
26154
+ await fs51.mkdir(targetDir, { recursive: true });
26155
+ await fs51.writeFile(targetPath, enrichedContent, "utf-8");
25646
26156
  return {
25647
26157
  name,
25648
26158
  filePath: targetPath,
@@ -25659,13 +26169,13 @@ async function installFromGitHub(source) {
25659
26169
  );
25660
26170
  return result;
25661
26171
  }
25662
- const tmpDir = path52.join(os15.tmpdir(), `prjct-skill-${Date.now()}`);
26172
+ const tmpDir = path54.join(os15.tmpdir(), `prjct-skill-${Date.now()}`);
25663
26173
  try {
25664
26174
  const cloneUrl = `https://github.com/${source.owner}/${source.repo}.git`;
25665
- await exec14(`git clone --depth 1 ${cloneUrl} ${tmpDir}`, { timeout: getTimeout("GIT_CLONE") });
26175
+ await exec15(`git clone --depth 1 ${cloneUrl} ${tmpDir}`, { timeout: getTimeout("GIT_CLONE") });
25666
26176
  let sha;
25667
26177
  try {
25668
- const { stdout } = await exec14("git rev-parse HEAD", {
26178
+ const { stdout } = await exec15("git rev-parse HEAD", {
25669
26179
  cwd: tmpDir,
25670
26180
  timeout: getTimeout("TOOL_CHECK")
25671
26181
  });
@@ -25703,7 +26213,7 @@ async function installFromGitHub(source) {
25703
26213
  }
25704
26214
  } finally {
25705
26215
  try {
25706
- await fs49.rm(tmpDir, { recursive: true, force: true });
26216
+ await fs51.rm(tmpDir, { recursive: true, force: true });
25707
26217
  } catch {
25708
26218
  }
25709
26219
  }
@@ -25713,14 +26223,14 @@ async function installFromLocal(source) {
25713
26223
  const result = { installed: [], skipped: [], errors: [] };
25714
26224
  const localPath = source.localPath;
25715
26225
  try {
25716
- await fs49.access(localPath);
26226
+ await fs51.access(localPath);
25717
26227
  } catch {
25718
26228
  result.errors.push(`Local path not found: ${localPath}`);
25719
26229
  return result;
25720
26230
  }
25721
- const stat = await fs49.stat(localPath);
26231
+ const stat = await fs51.stat(localPath);
25722
26232
  if (stat.isFile()) {
25723
- const name = path52.basename(path52.dirname(localPath));
26233
+ const name = path54.basename(path54.dirname(localPath));
25724
26234
  try {
25725
26235
  const installed = await installSkillFile(localPath, name, source);
25726
26236
  const lockEntry = {
@@ -25760,14 +26270,14 @@ async function installFromLocal(source) {
25760
26270
  }
25761
26271
  async function remove(name) {
25762
26272
  const installDir = getInstallDir();
25763
- const subdirPath = path52.join(installDir, name);
26273
+ const subdirPath = path54.join(installDir, name);
25764
26274
  try {
25765
- await fs49.rm(subdirPath, { recursive: true, force: true });
26275
+ await fs51.rm(subdirPath, { recursive: true, force: true });
25766
26276
  } catch {
25767
26277
  }
25768
- const flatPath = path52.join(installDir, `${name}.md`);
26278
+ const flatPath = path54.join(installDir, `${name}.md`);
25769
26279
  try {
25770
- await fs49.rm(flatPath, { force: true });
26280
+ await fs51.rm(flatPath, { force: true });
25771
26281
  } catch {
25772
26282
  }
25773
26283
  return skillLock.removeEntry(name);
@@ -25787,7 +26297,7 @@ async function install(sourceStr) {
25787
26297
  };
25788
26298
  }
25789
26299
  }
25790
- var exec14, skillInstaller;
26300
+ var exec15, skillInstaller;
25791
26301
  var init_skill_installer = __esm({
25792
26302
  "core/services/skill-installer.ts"() {
25793
26303
  "use strict";
@@ -25795,7 +26305,7 @@ var init_skill_installer = __esm({
25795
26305
  init_fs();
25796
26306
  init_dependency_validator();
25797
26307
  init_skill_lock();
25798
- exec14 = promisify15(execCallback7);
26308
+ exec15 = promisify16(execCallback8);
25799
26309
  __name(parseSource, "parseSource");
25800
26310
  __name(discoverSkills, "discoverSkills");
25801
26311
  __name(injectSourceMetadata, "injectSourceMetadata");
@@ -25815,8 +26325,8 @@ var init_skill_installer = __esm({
25815
26325
  });
25816
26326
 
25817
26327
  // core/services/stack-detector.ts
25818
- import fs50 from "node:fs/promises";
25819
- import path53 from "node:path";
26328
+ import fs52 from "node:fs/promises";
26329
+ import path55 from "node:path";
25820
26330
  var StackDetector;
25821
26331
  var init_stack_detector = __esm({
25822
26332
  "core/services/stack-detector.ts"() {
@@ -25975,8 +26485,8 @@ var init_stack_detector = __esm({
25975
26485
  */
25976
26486
  async readPackageJson() {
25977
26487
  try {
25978
- const pkgPath = path53.join(this.projectPath, "package.json");
25979
- const content = await fs50.readFile(pkgPath, "utf-8");
26488
+ const pkgPath = path55.join(this.projectPath, "package.json");
26489
+ const content = await fs52.readFile(pkgPath, "utf-8");
25980
26490
  return JSON.parse(content);
25981
26491
  } catch {
25982
26492
  return null;
@@ -25987,7 +26497,7 @@ var init_stack_detector = __esm({
25987
26497
  */
25988
26498
  async fileExists(filename) {
25989
26499
  try {
25990
- await fs50.access(path53.join(this.projectPath, filename));
26500
+ await fs52.access(path55.join(this.projectPath, filename));
25991
26501
  return true;
25992
26502
  } catch {
25993
26503
  return false;
@@ -25998,16 +26508,16 @@ var init_stack_detector = __esm({
25998
26508
  });
25999
26509
 
26000
26510
  // core/services/sync-verifier.ts
26001
- import { exec as exec15 } from "node:child_process";
26002
- import fs51 from "node:fs/promises";
26003
- import path54 from "node:path";
26004
- import { promisify as promisify16 } from "node:util";
26511
+ import { exec as exec16 } from "node:child_process";
26512
+ import fs53 from "node:fs/promises";
26513
+ import path56 from "node:path";
26514
+ import { promisify as promisify17 } from "node:util";
26005
26515
  var execAsync10, BUILTIN_CHECKS, SyncVerifier, syncVerifier;
26006
26516
  var init_sync_verifier = __esm({
26007
26517
  "core/services/sync-verifier.ts"() {
26008
26518
  "use strict";
26009
26519
  init_fs();
26010
- execAsync10 = promisify16(exec15);
26520
+ execAsync10 = promisify17(exec16);
26011
26521
  BUILTIN_CHECKS = {
26012
26522
  /**
26013
26523
  * Verify all expected context files exist after sync
@@ -26017,9 +26527,9 @@ var init_sync_verifier = __esm({
26017
26527
  const expected = ["context/CLAUDE.md"];
26018
26528
  const missing = [];
26019
26529
  for (const file of expected) {
26020
- const filePath = path54.join(globalPath, file);
26530
+ const filePath = path56.join(globalPath, file);
26021
26531
  try {
26022
- await fs51.access(filePath);
26532
+ await fs53.access(filePath);
26023
26533
  } catch {
26024
26534
  missing.push(file);
26025
26535
  }
@@ -26040,9 +26550,9 @@ var init_sync_verifier = __esm({
26040
26550
  const jsonFiles = ["storage/state.json"];
26041
26551
  const invalid = [];
26042
26552
  for (const file of jsonFiles) {
26043
- const filePath = path54.join(globalPath, file);
26553
+ const filePath = path56.join(globalPath, file);
26044
26554
  try {
26045
- const content = await fs51.readFile(filePath, "utf-8");
26555
+ const content = await fs53.readFile(filePath, "utf-8");
26046
26556
  JSON.parse(content);
26047
26557
  } catch (error) {
26048
26558
  if (!isNotFoundError(error)) {
@@ -26063,7 +26573,7 @@ var init_sync_verifier = __esm({
26063
26573
  */
26064
26574
  async noSensitiveData(globalPath) {
26065
26575
  const start = Date.now();
26066
- const contextDir = path54.join(globalPath, "context");
26576
+ const contextDir = path56.join(globalPath, "context");
26067
26577
  const patterns = [
26068
26578
  /(?:api[_-]?key|apikey)\s*[:=]\s*['"][^'"]{10,}/i,
26069
26579
  /(?:password|passwd|pwd)\s*[:=]\s*['"][^'"]{4,}/i,
@@ -26071,10 +26581,10 @@ var init_sync_verifier = __esm({
26071
26581
  ];
26072
26582
  const violations = [];
26073
26583
  try {
26074
- const files = await fs51.readdir(contextDir);
26584
+ const files = await fs53.readdir(contextDir);
26075
26585
  for (const file of files) {
26076
26586
  if (!file.endsWith(".md")) continue;
26077
- const content = await fs51.readFile(path54.join(contextDir, file), "utf-8");
26587
+ const content = await fs53.readFile(path56.join(contextDir, file), "utf-8");
26078
26588
  for (const pattern of patterns) {
26079
26589
  if (pattern.test(content)) {
26080
26590
  violations.push(`${file}: potential sensitive data detected`);
@@ -26194,16 +26704,19 @@ var init_sync_verifier = __esm({
26194
26704
  });
26195
26705
 
26196
26706
  // core/services/sync-service.ts
26197
- import { exec as exec16 } from "node:child_process";
26198
- import fs52 from "node:fs/promises";
26707
+ import { exec as exec17 } from "node:child_process";
26708
+ import fs54 from "node:fs/promises";
26199
26709
  import os16 from "node:os";
26200
- import path55 from "node:path";
26201
- import { promisify as promisify17 } from "node:util";
26710
+ import path57 from "node:path";
26711
+ import { promisify as promisify18 } from "node:util";
26202
26712
  var execAsync11, SyncService, syncService;
26203
26713
  var init_sync_service = __esm({
26204
26714
  "core/services/sync-service.ts"() {
26205
26715
  "use strict";
26206
26716
  init_ai_tools();
26717
+ init_bm25();
26718
+ init_git_cochange();
26719
+ init_import_graph();
26207
26720
  init_errors();
26208
26721
  init_command_installer();
26209
26722
  init_config_manager();
@@ -26219,7 +26732,7 @@ var init_sync_service = __esm({
26219
26732
  init_skill_installer();
26220
26733
  init_stack_detector();
26221
26734
  init_sync_verifier();
26222
- execAsync11 = promisify17(exec16);
26735
+ execAsync11 = promisify18(exec17);
26223
26736
  SyncService = class {
26224
26737
  static {
26225
26738
  __name(this, "SyncService");
@@ -26281,6 +26794,17 @@ var init_sync_service = __esm({
26281
26794
  this.detectCommands(),
26282
26795
  this.detectStack()
26283
26796
  ]);
26797
+ try {
26798
+ await Promise.all([
26799
+ indexProject(this.projectPath, this.projectId),
26800
+ indexImports(this.projectPath, this.projectId),
26801
+ indexCoChanges(this.projectPath, this.projectId)
26802
+ ]);
26803
+ } catch (error) {
26804
+ logger_default.debug("File ranking index build failed (non-critical)", {
26805
+ error: getErrorMessage(error)
26806
+ });
26807
+ }
26284
26808
  const agents = await this.generateAgents(stack, stats);
26285
26809
  const skills = this.configureSkills(agents);
26286
26810
  const skillsInstalled = await this.autoInstallSkills(agents);
@@ -26377,7 +26901,7 @@ var init_sync_service = __esm({
26377
26901
  async ensureDirectories() {
26378
26902
  const dirs = ["storage", "context", "agents", "memory", "analysis", "config", "sync"];
26379
26903
  await Promise.all(
26380
- dirs.map((dir) => fs52.mkdir(path55.join(this.globalPath, dir), { recursive: true }))
26904
+ dirs.map((dir) => fs54.mkdir(path57.join(this.globalPath, dir), { recursive: true }))
26381
26905
  );
26382
26906
  }
26383
26907
  // ==========================================================================
@@ -26448,7 +26972,7 @@ var init_sync_service = __esm({
26448
26972
  const stats = {
26449
26973
  fileCount: 0,
26450
26974
  version: "0.0.0",
26451
- name: path55.basename(this.projectPath),
26975
+ name: path57.basename(this.projectPath),
26452
26976
  ecosystem: "unknown",
26453
26977
  projectType: "simple",
26454
26978
  languages: [],
@@ -26465,8 +26989,8 @@ var init_sync_service = __esm({
26465
26989
  stats.fileCount = 0;
26466
26990
  }
26467
26991
  try {
26468
- const pkgPath = path55.join(this.projectPath, "package.json");
26469
- const pkg = JSON.parse(await fs52.readFile(pkgPath, "utf-8"));
26992
+ const pkgPath = path57.join(this.projectPath, "package.json");
26993
+ const pkg = JSON.parse(await fs54.readFile(pkgPath, "utf-8"));
26470
26994
  stats.version = pkg.version || "0.0.0";
26471
26995
  stats.name = pkg.name || stats.name;
26472
26996
  stats.ecosystem = "JavaScript";
@@ -26611,12 +27135,12 @@ var init_sync_service = __esm({
26611
27135
  // ==========================================================================
26612
27136
  async generateAgents(stack, stats) {
26613
27137
  const agents = [];
26614
- const agentsPath = path55.join(this.globalPath, "agents");
27138
+ const agentsPath = path57.join(this.globalPath, "agents");
26615
27139
  try {
26616
- const files = await fs52.readdir(agentsPath);
27140
+ const files = await fs54.readdir(agentsPath);
26617
27141
  for (const file of files) {
26618
27142
  if (file.endsWith(".md")) {
26619
- await fs52.unlink(path55.join(agentsPath, file));
27143
+ await fs54.unlink(path57.join(agentsPath, file));
26620
27144
  }
26621
27145
  }
26622
27146
  } catch (error) {
@@ -26665,7 +27189,7 @@ var init_sync_service = __esm({
26665
27189
  let resolved = content;
26666
27190
  for (const match of matches) {
26667
27191
  const partialName = match[1];
26668
- const partialPath = path55.join(
27192
+ const partialPath = path57.join(
26669
27193
  __dirname,
26670
27194
  "..",
26671
27195
  "..",
@@ -26674,7 +27198,7 @@ var init_sync_service = __esm({
26674
27198
  `${partialName}.md`
26675
27199
  );
26676
27200
  try {
26677
- const partialContent = await fs52.readFile(partialPath, "utf-8");
27201
+ const partialContent = await fs54.readFile(partialPath, "utf-8");
26678
27202
  resolved = resolved.replace(match[0], partialContent.trim());
26679
27203
  } catch {
26680
27204
  resolved = resolved.replace(match[0], `<!-- partial "${partialName}" not found -->`);
@@ -26685,7 +27209,7 @@ var init_sync_service = __esm({
26685
27209
  async generateWorkflowAgent(name, agentsPath) {
26686
27210
  let content = "";
26687
27211
  try {
26688
- const templatePath = path55.join(
27212
+ const templatePath = path57.join(
26689
27213
  __dirname,
26690
27214
  "..",
26691
27215
  "..",
@@ -26694,7 +27218,7 @@ var init_sync_service = __esm({
26694
27218
  "workflow",
26695
27219
  `${name}.md`
26696
27220
  );
26697
- content = await fs52.readFile(templatePath, "utf-8");
27221
+ content = await fs54.readFile(templatePath, "utf-8");
26698
27222
  content = await this.resolveTemplateIncludes(content);
26699
27223
  } catch (error) {
26700
27224
  logger_default.debug("Workflow agent template not found, generating minimal", {
@@ -26703,12 +27227,12 @@ var init_sync_service = __esm({
26703
27227
  });
26704
27228
  content = this.generateMinimalWorkflowAgent(name);
26705
27229
  }
26706
- await fs52.writeFile(path55.join(agentsPath, `${name}.md`), content, "utf-8");
27230
+ await fs54.writeFile(path57.join(agentsPath, `${name}.md`), content, "utf-8");
26707
27231
  }
26708
27232
  async generateDomainAgent(name, agentsPath, stats, stack) {
26709
27233
  let content = "";
26710
27234
  try {
26711
- const templatePath = path55.join(
27235
+ const templatePath = path57.join(
26712
27236
  __dirname,
26713
27237
  "..",
26714
27238
  "..",
@@ -26717,7 +27241,7 @@ var init_sync_service = __esm({
26717
27241
  "domain",
26718
27242
  `${name}.md`
26719
27243
  );
26720
- content = await fs52.readFile(templatePath, "utf-8");
27244
+ content = await fs54.readFile(templatePath, "utf-8");
26721
27245
  content = await this.resolveTemplateIncludes(content);
26722
27246
  content = content.replace("{projectName}", stats.name);
26723
27247
  content = content.replace("{frameworks}", stack.frameworks.join(", ") || "None detected");
@@ -26729,7 +27253,7 @@ var init_sync_service = __esm({
26729
27253
  });
26730
27254
  content = this.generateMinimalDomainAgent(name, stats, stack);
26731
27255
  }
26732
- await fs52.writeFile(path55.join(agentsPath, `${name}.md`), content, "utf-8");
27256
+ await fs54.writeFile(path57.join(agentsPath, `${name}.md`), content, "utf-8");
26733
27257
  }
26734
27258
  generateMinimalWorkflowAgent(name) {
26735
27259
  const descriptions = {
@@ -26797,8 +27321,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
26797
27321
  })),
26798
27322
  agentSkillMap: Object.fromEntries(skills.map((s) => [s.agent, s.skill]))
26799
27323
  };
26800
- fs52.writeFile(
26801
- path55.join(this.globalPath, "config", "skills.json"),
27324
+ fs54.writeFile(
27325
+ path57.join(this.globalPath, "config", "skills.json"),
26802
27326
  JSON.stringify(skillsConfig, null, 2),
26803
27327
  "utf-8"
26804
27328
  ).catch((error) => {
@@ -26816,7 +27340,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
26816
27340
  async autoInstallSkills(agents) {
26817
27341
  const results = [];
26818
27342
  try {
26819
- const mappingsPath = path55.join(
27343
+ const mappingsPath = path57.join(
26820
27344
  __dirname,
26821
27345
  "..",
26822
27346
  "..",
@@ -26824,7 +27348,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
26824
27348
  "config",
26825
27349
  "skill-mappings.json"
26826
27350
  );
26827
- const mappingsContent = await fs52.readFile(mappingsPath, "utf-8");
27351
+ const mappingsContent = await fs54.readFile(mappingsPath, "utf-8");
26828
27352
  const mappings = JSON.parse(mappingsContent);
26829
27353
  const agentToSkillMap = mappings.agentToSkillMap || {};
26830
27354
  const packagesToInstall = [];
@@ -26837,18 +27361,18 @@ You are the ${name} expert for this project. Apply best practices for the detect
26837
27361
  }
26838
27362
  }
26839
27363
  if (packagesToInstall.length === 0) return results;
26840
- const skillsDir = path55.join(os16.homedir(), ".claude", "skills");
27364
+ const skillsDir = path57.join(os16.homedir(), ".claude", "skills");
26841
27365
  for (const { pkg, agent } of packagesToInstall) {
26842
27366
  const skillName = pkg.split("/").pop() || pkg;
26843
- const subdirPath = path55.join(skillsDir, skillName, "SKILL.md");
26844
- const flatPath = path55.join(skillsDir, `${skillName}.md`);
27367
+ const subdirPath = path57.join(skillsDir, skillName, "SKILL.md");
27368
+ const flatPath = path57.join(skillsDir, `${skillName}.md`);
26845
27369
  let alreadyInstalled = false;
26846
27370
  try {
26847
- await fs52.access(subdirPath);
27371
+ await fs54.access(subdirPath);
26848
27372
  alreadyInstalled = true;
26849
27373
  } catch {
26850
27374
  try {
26851
- await fs52.access(flatPath);
27375
+ await fs54.access(flatPath);
26852
27376
  alreadyInstalled = true;
26853
27377
  } catch {
26854
27378
  }
@@ -26900,10 +27424,10 @@ You are the ${name} expert for this project. Apply best practices for the detect
26900
27424
  // PROJECT.JSON UPDATE
26901
27425
  // ==========================================================================
26902
27426
  async updateProjectJson(git, stats) {
26903
- const projectJsonPath = path55.join(this.globalPath, "project.json");
27427
+ const projectJsonPath = path57.join(this.globalPath, "project.json");
26904
27428
  let existing = {};
26905
27429
  try {
26906
- existing = JSON.parse(await fs52.readFile(projectJsonPath, "utf-8"));
27430
+ existing = JSON.parse(await fs54.readFile(projectJsonPath, "utf-8"));
26907
27431
  } catch (error) {
26908
27432
  logger_default.debug("No existing project.json", {
26909
27433
  path: projectJsonPath,
@@ -26929,16 +27453,16 @@ You are the ${name} expert for this project. Apply best practices for the detect
26929
27453
  lastSyncCommit: git.recentCommits[0]?.hash || null,
26930
27454
  lastSyncBranch: git.branch
26931
27455
  };
26932
- await fs52.writeFile(projectJsonPath, JSON.stringify(updated, null, 2), "utf-8");
27456
+ await fs54.writeFile(projectJsonPath, JSON.stringify(updated, null, 2), "utf-8");
26933
27457
  }
26934
27458
  // ==========================================================================
26935
27459
  // STATE.JSON UPDATE
26936
27460
  // ==========================================================================
26937
27461
  async updateStateJson(stats, stack) {
26938
- const statePath = path55.join(this.globalPath, "storage", "state.json");
27462
+ const statePath = path57.join(this.globalPath, "storage", "state.json");
26939
27463
  let state = {};
26940
27464
  try {
26941
- state = JSON.parse(await fs52.readFile(statePath, "utf-8"));
27465
+ state = JSON.parse(await fs54.readFile(statePath, "utf-8"));
26942
27466
  } catch (error) {
26943
27467
  logger_default.debug("No existing state.json", { path: statePath, error: getErrorMessage(error) });
26944
27468
  }
@@ -26966,7 +27490,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
26966
27490
  lastAction: "Synced project",
26967
27491
  nextAction: 'Run `p. task "description"` to start working'
26968
27492
  };
26969
- await fs52.writeFile(statePath, JSON.stringify(state, null, 2), "utf-8");
27493
+ await fs54.writeFile(statePath, JSON.stringify(state, null, 2), "utf-8");
26970
27494
  try {
26971
27495
  await localStateGenerator.generate(
26972
27496
  this.projectPath,
@@ -26980,7 +27504,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
26980
27504
  // MEMORY LOGGING
26981
27505
  // ==========================================================================
26982
27506
  async logToMemory(git, stats) {
26983
- const memoryPath = path55.join(this.globalPath, "memory", "events.jsonl");
27507
+ const memoryPath = path57.join(this.globalPath, "memory", "events.jsonl");
26984
27508
  const event = {
26985
27509
  ts: getTimestamp(),
26986
27510
  action: "sync",
@@ -26989,7 +27513,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
26989
27513
  fileCount: stats.fileCount,
26990
27514
  commitCount: git.commits
26991
27515
  };
26992
- await fs52.appendFile(memoryPath, `${JSON.stringify(event)}
27516
+ await fs54.appendFile(memoryPath, `${JSON.stringify(event)}
26993
27517
  `, "utf-8");
26994
27518
  }
26995
27519
  // ==========================================================================
@@ -27009,8 +27533,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
27009
27533
  let filteredChars = 0;
27010
27534
  for (const file of contextFiles) {
27011
27535
  try {
27012
- const filePath = path55.join(this.globalPath, file);
27013
- const content = await fs52.readFile(filePath, "utf-8");
27536
+ const filePath = path57.join(this.globalPath, file);
27537
+ const content = await fs54.readFile(filePath, "utf-8");
27014
27538
  filteredChars += content.length;
27015
27539
  } catch (error) {
27016
27540
  logger_default.debug("Context file not found for metrics", { file, error: getErrorMessage(error) });
@@ -27018,8 +27542,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
27018
27542
  }
27019
27543
  for (const agent of agents) {
27020
27544
  try {
27021
- const agentPath = path55.join(this.globalPath, "agents", `${agent.name}.md`);
27022
- const content = await fs52.readFile(agentPath, "utf-8");
27545
+ const agentPath = path57.join(this.globalPath, "agents", `${agent.name}.md`);
27546
+ const content = await fs54.readFile(agentPath, "utf-8");
27023
27547
  filteredChars += content.length;
27024
27548
  } catch (error) {
27025
27549
  logger_default.debug("Agent file not found for metrics", {
@@ -27081,7 +27605,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
27081
27605
  // ==========================================================================
27082
27606
  async fileExists(filename) {
27083
27607
  try {
27084
- await fs52.access(path55.join(this.projectPath, filename));
27608
+ await fs54.access(path57.join(this.projectPath, filename));
27085
27609
  return true;
27086
27610
  } catch (error) {
27087
27611
  logger_default.debug("File not found", { filename, error: getErrorMessage(error) });
@@ -27090,8 +27614,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
27090
27614
  }
27091
27615
  async getCliVersion() {
27092
27616
  try {
27093
- const pkgPath = path55.join(__dirname, "..", "..", "package.json");
27094
- const pkg = JSON.parse(await fs52.readFile(pkgPath, "utf-8"));
27617
+ const pkgPath = path57.join(__dirname, "..", "..", "package.json");
27618
+ const pkg = JSON.parse(await fs54.readFile(pkgPath, "utf-8"));
27095
27619
  return pkg.version || "0.0.0";
27096
27620
  } catch (error) {
27097
27621
  logger_default.debug("Failed to read CLI version", { error: getErrorMessage(error) });
@@ -27252,22 +27776,22 @@ __export(uninstall_exports, {
27252
27776
  uninstall: () => uninstall
27253
27777
  });
27254
27778
  import { execSync as execSync3 } from "node:child_process";
27255
- import fs53 from "node:fs/promises";
27779
+ import fs55 from "node:fs/promises";
27256
27780
  import os17 from "node:os";
27257
- import path56 from "node:path";
27781
+ import path58 from "node:path";
27258
27782
  import readline2 from "node:readline";
27259
27783
  import chalk12 from "chalk";
27260
27784
  async function getDirectorySize(dirPath) {
27261
27785
  let totalSize = 0;
27262
27786
  try {
27263
- const entries = await fs53.readdir(dirPath, { withFileTypes: true });
27787
+ const entries = await fs55.readdir(dirPath, { withFileTypes: true });
27264
27788
  for (const entry of entries) {
27265
- const entryPath = path56.join(dirPath, entry.name);
27789
+ const entryPath = path58.join(dirPath, entry.name);
27266
27790
  if (entry.isDirectory()) {
27267
27791
  totalSize += await getDirectorySize(entryPath);
27268
27792
  } else {
27269
27793
  try {
27270
- const stats = await fs53.stat(entryPath);
27794
+ const stats = await fs55.stat(entryPath);
27271
27795
  totalSize += stats.size;
27272
27796
  } catch {
27273
27797
  }
@@ -27286,7 +27810,7 @@ function formatSize(bytes) {
27286
27810
  }
27287
27811
  async function countDirectoryItems(dirPath) {
27288
27812
  try {
27289
- const entries = await fs53.readdir(dirPath, { withFileTypes: true });
27813
+ const entries = await fs55.readdir(dirPath, { withFileTypes: true });
27290
27814
  return entries.filter((e) => e.isDirectory()).length;
27291
27815
  } catch {
27292
27816
  return 0;
@@ -27319,7 +27843,7 @@ async function gatherUninstallItems() {
27319
27843
  const providerPaths = getProviderPaths();
27320
27844
  const prjctCliPath = path_manager_default.getGlobalBasePath();
27321
27845
  const prjctCliExists = await fileExists(prjctCliPath);
27322
- const projectCount = prjctCliExists ? await countDirectoryItems(path56.join(prjctCliPath, "projects")) : 0;
27846
+ const projectCount = prjctCliExists ? await countDirectoryItems(path58.join(prjctCliPath, "projects")) : 0;
27323
27847
  const prjctCliSize = prjctCliExists ? await getDirectorySize(prjctCliPath) : 0;
27324
27848
  items.push({
27325
27849
  path: prjctCliPath,
@@ -27329,12 +27853,12 @@ async function gatherUninstallItems() {
27329
27853
  count: projectCount,
27330
27854
  exists: prjctCliExists
27331
27855
  });
27332
- const claudeMdPath = path56.join(providerPaths.claude.config, "CLAUDE.md");
27856
+ const claudeMdPath = path58.join(providerPaths.claude.config, "CLAUDE.md");
27333
27857
  const claudeMdExists = await fileExists(claudeMdPath);
27334
27858
  let hasPrjctSection = false;
27335
27859
  if (claudeMdExists) {
27336
27860
  try {
27337
- const content = await fs53.readFile(claudeMdPath, "utf-8");
27861
+ const content = await fs55.readFile(claudeMdPath, "utf-8");
27338
27862
  hasPrjctSection = content.includes(PRJCT_START_MARKER) && content.includes(PRJCT_END_MARKER);
27339
27863
  } catch {
27340
27864
  }
@@ -27363,7 +27887,7 @@ async function gatherUninstallItems() {
27363
27887
  description: "Claude router",
27364
27888
  exists: claudeRouterExists
27365
27889
  });
27366
- const statusLinePath = path56.join(providerPaths.claude.config, "prjct-statusline.sh");
27890
+ const statusLinePath = path58.join(providerPaths.claude.config, "prjct-statusline.sh");
27367
27891
  const statusLineExists = await fileExists(statusLinePath);
27368
27892
  items.push({
27369
27893
  path: statusLinePath,
@@ -27379,12 +27903,12 @@ async function gatherUninstallItems() {
27379
27903
  description: "Gemini router",
27380
27904
  exists: geminiRouterExists
27381
27905
  });
27382
- const geminiMdPath = path56.join(providerPaths.gemini.config, "GEMINI.md");
27906
+ const geminiMdPath = path58.join(providerPaths.gemini.config, "GEMINI.md");
27383
27907
  const geminiMdExists = await fileExists(geminiMdPath);
27384
27908
  let hasGeminiPrjctSection = false;
27385
27909
  if (geminiMdExists) {
27386
27910
  try {
27387
- const content = await fs53.readFile(geminiMdPath, "utf-8");
27911
+ const content = await fs55.readFile(geminiMdPath, "utf-8");
27388
27912
  hasGeminiPrjctSection = content.includes(PRJCT_START_MARKER) && content.includes(PRJCT_END_MARKER);
27389
27913
  } catch {
27390
27914
  }
@@ -27401,7 +27925,7 @@ async function gatherUninstallItems() {
27401
27925
  }
27402
27926
  async function removePrjctSection(filePath) {
27403
27927
  try {
27404
- const content = await fs53.readFile(filePath, "utf-8");
27928
+ const content = await fs55.readFile(filePath, "utf-8");
27405
27929
  if (!content.includes(PRJCT_START_MARKER) || !content.includes(PRJCT_END_MARKER)) {
27406
27930
  return false;
27407
27931
  }
@@ -27410,9 +27934,9 @@ async function removePrjctSection(filePath) {
27410
27934
  let newContent = content.substring(0, startIndex) + content.substring(endIndex);
27411
27935
  newContent = newContent.replace(/\n{3,}/g, "\n\n").trim();
27412
27936
  if (!newContent || newContent.trim().length === 0) {
27413
- await fs53.unlink(filePath);
27937
+ await fs55.unlink(filePath);
27414
27938
  } else {
27415
- await fs53.writeFile(filePath, `${newContent}
27939
+ await fs55.writeFile(filePath, `${newContent}
27416
27940
  `, "utf-8");
27417
27941
  }
27418
27942
  return true;
@@ -27423,12 +27947,12 @@ async function removePrjctSection(filePath) {
27423
27947
  async function createBackup3() {
27424
27948
  const homeDir = os17.homedir();
27425
27949
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
27426
- const backupDir = path56.join(homeDir, `.prjct-backup-${timestamp}`);
27950
+ const backupDir = path58.join(homeDir, `.prjct-backup-${timestamp}`);
27427
27951
  try {
27428
- await fs53.mkdir(backupDir, { recursive: true });
27952
+ await fs55.mkdir(backupDir, { recursive: true });
27429
27953
  const prjctCliPath = path_manager_default.getGlobalBasePath();
27430
27954
  if (await fileExists(prjctCliPath)) {
27431
- await copyDirectory(prjctCliPath, path56.join(backupDir, ".prjct-cli"));
27955
+ await copyDirectory(prjctCliPath, path58.join(backupDir, ".prjct-cli"));
27432
27956
  }
27433
27957
  return backupDir;
27434
27958
  } catch {
@@ -27436,15 +27960,15 @@ async function createBackup3() {
27436
27960
  }
27437
27961
  }
27438
27962
  async function copyDirectory(src, dest) {
27439
- await fs53.mkdir(dest, { recursive: true });
27440
- const entries = await fs53.readdir(src, { withFileTypes: true });
27963
+ await fs55.mkdir(dest, { recursive: true });
27964
+ const entries = await fs55.readdir(src, { withFileTypes: true });
27441
27965
  for (const entry of entries) {
27442
- const srcPath = path56.join(src, entry.name);
27443
- const destPath = path56.join(dest, entry.name);
27966
+ const srcPath = path58.join(src, entry.name);
27967
+ const destPath = path58.join(dest, entry.name);
27444
27968
  if (entry.isDirectory()) {
27445
27969
  await copyDirectory(srcPath, destPath);
27446
27970
  } else {
27447
- await fs53.copyFile(srcPath, destPath);
27971
+ await fs55.copyFile(srcPath, destPath);
27448
27972
  }
27449
27973
  }
27450
27974
  }
@@ -27460,10 +27984,10 @@ async function performUninstall(items, installation, options) {
27460
27984
  deleted.push(item.path);
27461
27985
  }
27462
27986
  } else if (item.type === "directory") {
27463
- await fs53.rm(item.path, { recursive: true, force: true });
27987
+ await fs55.rm(item.path, { recursive: true, force: true });
27464
27988
  deleted.push(item.path);
27465
27989
  } else if (item.type === "file") {
27466
- await fs53.unlink(item.path);
27990
+ await fs55.unlink(item.path);
27467
27991
  deleted.push(item.path);
27468
27992
  }
27469
27993
  } catch (error) {
@@ -27640,7 +28164,7 @@ __export(watch_service_exports, {
27640
28164
  WatchService: () => WatchService,
27641
28165
  watchService: () => watchService
27642
28166
  });
27643
- import path57 from "node:path";
28167
+ import path59 from "node:path";
27644
28168
  import chalk13 from "chalk";
27645
28169
  import chokidar from "chokidar";
27646
28170
  var TRIGGER_PATTERNS, IGNORE_PATTERNS2, WatchService, watchService;
@@ -27861,7 +28385,7 @@ ${chalk13.dim(`[${timestamp}]`)} ${chalk13.cyan("\u27F3")} ${filesSummary} chang
27861
28385
  printStartup() {
27862
28386
  console.log("");
27863
28387
  console.log(chalk13.cyan("\u{1F441}\uFE0F Watching for changes..."));
27864
- console.log(chalk13.dim(` Project: ${path57.basename(this.projectPath)}`));
28388
+ console.log(chalk13.dim(` Project: ${path59.basename(this.projectPath)}`));
27865
28389
  console.log(chalk13.dim(` Debounce: ${this.options.debounceMs}ms`));
27866
28390
  console.log(chalk13.dim(` Min interval: ${this.options.minIntervalMs / 1e3}s`));
27867
28391
  console.log("");
@@ -28592,9 +29116,9 @@ __export(setup_exports, {
28592
29116
  run: () => run
28593
29117
  });
28594
29118
  import { execSync as execSync4 } from "node:child_process";
28595
- import fs54 from "node:fs/promises";
29119
+ import fs56 from "node:fs/promises";
28596
29120
  import os18 from "node:os";
28597
- import path58 from "node:path";
29121
+ import path60 from "node:path";
28598
29122
  import chalk15 from "chalk";
28599
29123
  async function installAICLI(provider) {
28600
29124
  const packageName = provider.name === "claude" ? "@anthropic-ai/claude-code" : "@google/gemini-cli";
@@ -28733,12 +29257,12 @@ async function run() {
28733
29257
  }
28734
29258
  async function installGeminiRouter() {
28735
29259
  try {
28736
- const geminiCommandsDir = path58.join(os18.homedir(), ".gemini", "commands");
28737
- const routerSource = path58.join(PACKAGE_ROOT, "templates", "commands", "p.toml");
28738
- const routerDest = path58.join(geminiCommandsDir, "p.toml");
28739
- await fs54.mkdir(geminiCommandsDir, { recursive: true });
29260
+ const geminiCommandsDir = path60.join(os18.homedir(), ".gemini", "commands");
29261
+ const routerSource = path60.join(PACKAGE_ROOT, "templates", "commands", "p.toml");
29262
+ const routerDest = path60.join(geminiCommandsDir, "p.toml");
29263
+ await fs56.mkdir(geminiCommandsDir, { recursive: true });
28740
29264
  if (await fileExists(routerSource)) {
28741
- await fs54.copyFile(routerSource, routerDest);
29265
+ await fs56.copyFile(routerSource, routerDest);
28742
29266
  return true;
28743
29267
  }
28744
29268
  return false;
@@ -28749,15 +29273,15 @@ async function installGeminiRouter() {
28749
29273
  }
28750
29274
  async function installGeminiGlobalConfig() {
28751
29275
  try {
28752
- const geminiDir = path58.join(os18.homedir(), ".gemini");
28753
- const globalConfigPath = path58.join(geminiDir, "GEMINI.md");
28754
- const templatePath = path58.join(PACKAGE_ROOT, "templates", "global", "GEMINI.md");
28755
- await fs54.mkdir(geminiDir, { recursive: true });
28756
- const templateContent = await fs54.readFile(templatePath, "utf-8");
29276
+ const geminiDir = path60.join(os18.homedir(), ".gemini");
29277
+ const globalConfigPath = path60.join(geminiDir, "GEMINI.md");
29278
+ const templatePath = path60.join(PACKAGE_ROOT, "templates", "global", "GEMINI.md");
29279
+ await fs56.mkdir(geminiDir, { recursive: true });
29280
+ const templateContent = await fs56.readFile(templatePath, "utf-8");
28757
29281
  let existingContent = "";
28758
29282
  let configExists = false;
28759
29283
  try {
28760
- existingContent = await fs54.readFile(globalConfigPath, "utf-8");
29284
+ existingContent = await fs56.readFile(globalConfigPath, "utf-8");
28761
29285
  configExists = true;
28762
29286
  } catch (error) {
28763
29287
  if (isNotFoundError(error)) {
@@ -28767,7 +29291,7 @@ async function installGeminiGlobalConfig() {
28767
29291
  }
28768
29292
  }
28769
29293
  if (!configExists) {
28770
- await fs54.writeFile(globalConfigPath, templateContent, "utf-8");
29294
+ await fs56.writeFile(globalConfigPath, templateContent, "utf-8");
28771
29295
  return { success: true, action: "created" };
28772
29296
  }
28773
29297
  const startMarker = "<!-- prjct:start - DO NOT REMOVE THIS MARKER -->";
@@ -28777,7 +29301,7 @@ async function installGeminiGlobalConfig() {
28777
29301
  const updatedContent2 = `${existingContent}
28778
29302
 
28779
29303
  ${templateContent}`;
28780
- await fs54.writeFile(globalConfigPath, updatedContent2, "utf-8");
29304
+ await fs56.writeFile(globalConfigPath, updatedContent2, "utf-8");
28781
29305
  return { success: true, action: "appended" };
28782
29306
  }
28783
29307
  const beforeMarker = existingContent.substring(0, existingContent.indexOf(startMarker));
@@ -28789,7 +29313,7 @@ ${templateContent}`;
28789
29313
  templateContent.indexOf(endMarker) + endMarker.length
28790
29314
  );
28791
29315
  const updatedContent = beforeMarker + prjctSection + afterMarker;
28792
- await fs54.writeFile(globalConfigPath, updatedContent, "utf-8");
29316
+ await fs56.writeFile(globalConfigPath, updatedContent, "utf-8");
28793
29317
  return { success: true, action: "updated" };
28794
29318
  } catch (error) {
28795
29319
  logger_default.warn(`Gemini config warning: ${getErrorMessage2(error)}`);
@@ -28798,18 +29322,18 @@ ${templateContent}`;
28798
29322
  }
28799
29323
  async function installAntigravitySkill() {
28800
29324
  try {
28801
- const antigravitySkillsDir = path58.join(os18.homedir(), ".gemini", "antigravity", "skills");
28802
- const prjctSkillDir = path58.join(antigravitySkillsDir, "prjct");
28803
- const skillMdPath = path58.join(prjctSkillDir, "SKILL.md");
28804
- const templatePath = path58.join(PACKAGE_ROOT, "templates", "antigravity", "SKILL.md");
28805
- await fs54.mkdir(prjctSkillDir, { recursive: true });
29325
+ const antigravitySkillsDir = path60.join(os18.homedir(), ".gemini", "antigravity", "skills");
29326
+ const prjctSkillDir = path60.join(antigravitySkillsDir, "prjct");
29327
+ const skillMdPath = path60.join(prjctSkillDir, "SKILL.md");
29328
+ const templatePath = path60.join(PACKAGE_ROOT, "templates", "antigravity", "SKILL.md");
29329
+ await fs56.mkdir(prjctSkillDir, { recursive: true });
28806
29330
  const skillExists = await fileExists(skillMdPath);
28807
29331
  if (!await fileExists(templatePath)) {
28808
29332
  logger_default.warn("Antigravity SKILL.md template not found");
28809
29333
  return { success: false, action: null };
28810
29334
  }
28811
- const templateContent = await fs54.readFile(templatePath, "utf-8");
28812
- await fs54.writeFile(skillMdPath, templateContent, "utf-8");
29335
+ const templateContent = await fs56.readFile(templatePath, "utf-8");
29336
+ await fs56.writeFile(skillMdPath, templateContent, "utf-8");
28813
29337
  return { success: true, action: skillExists ? "updated" : "created" };
28814
29338
  } catch (error) {
28815
29339
  logger_default.warn(`Antigravity skill warning: ${getErrorMessage2(error)}`);
@@ -28828,24 +29352,24 @@ async function installCursorProject(projectRoot) {
28828
29352
  gitignoreUpdated: false
28829
29353
  };
28830
29354
  try {
28831
- const cursorDir = path58.join(projectRoot, ".cursor");
28832
- const rulesDir = path58.join(cursorDir, "rules");
28833
- const commandsDir = path58.join(cursorDir, "commands");
28834
- const routerMdcDest = path58.join(rulesDir, "prjct.mdc");
28835
- const routerMdcSource = path58.join(PACKAGE_ROOT, "templates", "cursor", "router.mdc");
28836
- const cursorCommandsSource = path58.join(PACKAGE_ROOT, "templates", "cursor", "commands");
28837
- await fs54.mkdir(rulesDir, { recursive: true });
28838
- await fs54.mkdir(commandsDir, { recursive: true });
29355
+ const cursorDir = path60.join(projectRoot, ".cursor");
29356
+ const rulesDir = path60.join(cursorDir, "rules");
29357
+ const commandsDir = path60.join(cursorDir, "commands");
29358
+ const routerMdcDest = path60.join(rulesDir, "prjct.mdc");
29359
+ const routerMdcSource = path60.join(PACKAGE_ROOT, "templates", "cursor", "router.mdc");
29360
+ const cursorCommandsSource = path60.join(PACKAGE_ROOT, "templates", "cursor", "commands");
29361
+ await fs56.mkdir(rulesDir, { recursive: true });
29362
+ await fs56.mkdir(commandsDir, { recursive: true });
28839
29363
  if (await fileExists(routerMdcSource)) {
28840
- await fs54.copyFile(routerMdcSource, routerMdcDest);
29364
+ await fs56.copyFile(routerMdcSource, routerMdcDest);
28841
29365
  result.rulesCreated = true;
28842
29366
  }
28843
29367
  if (await fileExists(cursorCommandsSource)) {
28844
- const commandFiles = (await fs54.readdir(cursorCommandsSource)).filter((f) => f.endsWith(".md"));
29368
+ const commandFiles = (await fs56.readdir(cursorCommandsSource)).filter((f) => f.endsWith(".md"));
28845
29369
  for (const file of commandFiles) {
28846
- const src = path58.join(cursorCommandsSource, file);
28847
- const dest = path58.join(commandsDir, file);
28848
- await fs54.copyFile(src, dest);
29370
+ const src = path60.join(cursorCommandsSource, file);
29371
+ const dest = path60.join(commandsDir, file);
29372
+ await fs56.copyFile(src, dest);
28849
29373
  }
28850
29374
  result.commandsCreated = commandFiles.length > 0;
28851
29375
  }
@@ -28859,7 +29383,7 @@ async function installCursorProject(projectRoot) {
28859
29383
  }
28860
29384
  async function addCursorToGitignore(projectRoot) {
28861
29385
  try {
28862
- const gitignorePath = path58.join(projectRoot, ".gitignore");
29386
+ const gitignorePath = path60.join(projectRoot, ".gitignore");
28863
29387
  const entriesToAdd = [
28864
29388
  "# prjct Cursor routers (regenerated per-developer)",
28865
29389
  ".cursor/rules/prjct.mdc",
@@ -28874,7 +29398,7 @@ async function addCursorToGitignore(projectRoot) {
28874
29398
  let content = "";
28875
29399
  let configExists = false;
28876
29400
  try {
28877
- content = await fs54.readFile(gitignorePath, "utf-8");
29401
+ content = await fs56.readFile(gitignorePath, "utf-8");
28878
29402
  configExists = true;
28879
29403
  } catch (error) {
28880
29404
  if (!isNotFoundError(error)) {
@@ -28889,7 +29413,7 @@ async function addCursorToGitignore(projectRoot) {
28889
29413
  ${entriesToAdd.join("\n")}
28890
29414
  ` : `${entriesToAdd.join("\n")}
28891
29415
  `;
28892
- await fs54.writeFile(gitignorePath, newContent, "utf-8");
29416
+ await fs56.writeFile(gitignorePath, newContent, "utf-8");
28893
29417
  return true;
28894
29418
  } catch (error) {
28895
29419
  logger_default.warn(`Gitignore update warning: ${getErrorMessage2(error)}`);
@@ -28897,11 +29421,11 @@ ${entriesToAdd.join("\n")}
28897
29421
  }
28898
29422
  }
28899
29423
  async function hasCursorProject(projectRoot) {
28900
- return await fileExists(path58.join(projectRoot, ".cursor"));
29424
+ return await fileExists(path60.join(projectRoot, ".cursor"));
28901
29425
  }
28902
29426
  async function needsCursorRegeneration(projectRoot) {
28903
- const cursorDir = path58.join(projectRoot, ".cursor");
28904
- const routerPath = path58.join(cursorDir, "rules", "prjct.mdc");
29427
+ const cursorDir = path60.join(projectRoot, ".cursor");
29428
+ const routerPath = path60.join(cursorDir, "rules", "prjct.mdc");
28905
29429
  return await fileExists(cursorDir) && !await fileExists(routerPath);
28906
29430
  }
28907
29431
  async function installWindsurfProject(projectRoot) {
@@ -28912,26 +29436,26 @@ async function installWindsurfProject(projectRoot) {
28912
29436
  gitignoreUpdated: false
28913
29437
  };
28914
29438
  try {
28915
- const windsurfDir = path58.join(projectRoot, ".windsurf");
28916
- const rulesDir = path58.join(windsurfDir, "rules");
28917
- const workflowsDir = path58.join(windsurfDir, "workflows");
28918
- const routerDest = path58.join(rulesDir, "prjct.md");
28919
- const routerSource = path58.join(PACKAGE_ROOT, "templates", "windsurf", "router.md");
28920
- const windsurfWorkflowsSource = path58.join(PACKAGE_ROOT, "templates", "windsurf", "workflows");
28921
- await fs54.mkdir(rulesDir, { recursive: true });
28922
- await fs54.mkdir(workflowsDir, { recursive: true });
29439
+ const windsurfDir = path60.join(projectRoot, ".windsurf");
29440
+ const rulesDir = path60.join(windsurfDir, "rules");
29441
+ const workflowsDir = path60.join(windsurfDir, "workflows");
29442
+ const routerDest = path60.join(rulesDir, "prjct.md");
29443
+ const routerSource = path60.join(PACKAGE_ROOT, "templates", "windsurf", "router.md");
29444
+ const windsurfWorkflowsSource = path60.join(PACKAGE_ROOT, "templates", "windsurf", "workflows");
29445
+ await fs56.mkdir(rulesDir, { recursive: true });
29446
+ await fs56.mkdir(workflowsDir, { recursive: true });
28923
29447
  if (await fileExists(routerSource)) {
28924
- await fs54.copyFile(routerSource, routerDest);
29448
+ await fs56.copyFile(routerSource, routerDest);
28925
29449
  result.rulesCreated = true;
28926
29450
  }
28927
29451
  if (await fileExists(windsurfWorkflowsSource)) {
28928
- const workflowFiles = (await fs54.readdir(windsurfWorkflowsSource)).filter(
29452
+ const workflowFiles = (await fs56.readdir(windsurfWorkflowsSource)).filter(
28929
29453
  (f) => f.endsWith(".md")
28930
29454
  );
28931
29455
  for (const file of workflowFiles) {
28932
- const src = path58.join(windsurfWorkflowsSource, file);
28933
- const dest = path58.join(workflowsDir, file);
28934
- await fs54.copyFile(src, dest);
29456
+ const src = path60.join(windsurfWorkflowsSource, file);
29457
+ const dest = path60.join(workflowsDir, file);
29458
+ await fs56.copyFile(src, dest);
28935
29459
  }
28936
29460
  result.workflowsCreated = workflowFiles.length > 0;
28937
29461
  }
@@ -28945,7 +29469,7 @@ async function installWindsurfProject(projectRoot) {
28945
29469
  }
28946
29470
  async function addWindsurfToGitignore(projectRoot) {
28947
29471
  try {
28948
- const gitignorePath = path58.join(projectRoot, ".gitignore");
29472
+ const gitignorePath = path60.join(projectRoot, ".gitignore");
28949
29473
  const entriesToAdd = [
28950
29474
  "# prjct Windsurf routers (regenerated per-developer)",
28951
29475
  ".windsurf/rules/prjct.md",
@@ -28960,7 +29484,7 @@ async function addWindsurfToGitignore(projectRoot) {
28960
29484
  let content = "";
28961
29485
  let configExists = false;
28962
29486
  try {
28963
- content = await fs54.readFile(gitignorePath, "utf-8");
29487
+ content = await fs56.readFile(gitignorePath, "utf-8");
28964
29488
  configExists = true;
28965
29489
  } catch (error) {
28966
29490
  if (!isNotFoundError(error)) {
@@ -28975,7 +29499,7 @@ async function addWindsurfToGitignore(projectRoot) {
28975
29499
  ${entriesToAdd.join("\n")}
28976
29500
  ` : `${entriesToAdd.join("\n")}
28977
29501
  `;
28978
- await fs54.writeFile(gitignorePath, newContent, "utf-8");
29502
+ await fs56.writeFile(gitignorePath, newContent, "utf-8");
28979
29503
  return true;
28980
29504
  } catch (error) {
28981
29505
  logger_default.warn(`Gitignore update warning: ${getErrorMessage2(error)}`);
@@ -28983,32 +29507,32 @@ ${entriesToAdd.join("\n")}
28983
29507
  }
28984
29508
  }
28985
29509
  async function hasWindsurfProject(projectRoot) {
28986
- return await fileExists(path58.join(projectRoot, ".windsurf"));
29510
+ return await fileExists(path60.join(projectRoot, ".windsurf"));
28987
29511
  }
28988
29512
  async function needsWindsurfRegeneration(projectRoot) {
28989
- const windsurfDir = path58.join(projectRoot, ".windsurf");
28990
- const routerPath = path58.join(windsurfDir, "rules", "prjct.md");
29513
+ const windsurfDir = path60.join(projectRoot, ".windsurf");
29514
+ const routerPath = path60.join(windsurfDir, "rules", "prjct.md");
28991
29515
  return await fileExists(windsurfDir) && !await fileExists(routerPath);
28992
29516
  }
28993
29517
  async function migrateProjectsCliVersion() {
28994
29518
  try {
28995
- const projectsDir = path58.join(os18.homedir(), ".prjct-cli", "projects");
29519
+ const projectsDir = path60.join(os18.homedir(), ".prjct-cli", "projects");
28996
29520
  if (!await fileExists(projectsDir)) {
28997
29521
  return;
28998
29522
  }
28999
- const projectDirs = (await fs54.readdir(projectsDir, { withFileTypes: true })).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
29523
+ const projectDirs = (await fs56.readdir(projectsDir, { withFileTypes: true })).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
29000
29524
  let migrated = 0;
29001
29525
  for (const projectId of projectDirs) {
29002
- const projectJsonPath = path58.join(projectsDir, projectId, "project.json");
29526
+ const projectJsonPath = path60.join(projectsDir, projectId, "project.json");
29003
29527
  if (!await fileExists(projectJsonPath)) {
29004
29528
  continue;
29005
29529
  }
29006
29530
  try {
29007
- const content = await fs54.readFile(projectJsonPath, "utf8");
29531
+ const content = await fs56.readFile(projectJsonPath, "utf8");
29008
29532
  const project = JSON.parse(content);
29009
29533
  if (project.cliVersion !== VERSION) {
29010
29534
  project.cliVersion = VERSION;
29011
- await fs54.writeFile(projectJsonPath, JSON.stringify(project, null, 2));
29535
+ await fs56.writeFile(projectJsonPath, JSON.stringify(project, null, 2));
29012
29536
  migrated++;
29013
29537
  }
29014
29538
  } catch (error) {
@@ -29030,7 +29554,7 @@ async function ensureStatusLineSettings(settingsPath, statusLinePath) {
29030
29554
  let settings = {};
29031
29555
  if (await fileExists(settingsPath)) {
29032
29556
  try {
29033
- settings = JSON.parse(await fs54.readFile(settingsPath, "utf8"));
29557
+ settings = JSON.parse(await fs56.readFile(settingsPath, "utf8"));
29034
29558
  } catch (error) {
29035
29559
  if (!(error instanceof SyntaxError)) {
29036
29560
  throw error;
@@ -29038,42 +29562,42 @@ async function ensureStatusLineSettings(settingsPath, statusLinePath) {
29038
29562
  }
29039
29563
  }
29040
29564
  settings.statusLine = { type: "command", command: statusLinePath };
29041
- await fs54.writeFile(settingsPath, JSON.stringify(settings, null, 2));
29565
+ await fs56.writeFile(settingsPath, JSON.stringify(settings, null, 2));
29042
29566
  }
29043
29567
  async function installStatusLine() {
29044
29568
  try {
29045
- const claudeDir = path58.join(os18.homedir(), ".claude");
29046
- const settingsPath = path58.join(claudeDir, "settings.json");
29047
- const claudeStatusLinePath = path58.join(claudeDir, "prjct-statusline.sh");
29048
- const prjctStatusLineDir = path58.join(os18.homedir(), ".prjct-cli", "statusline");
29049
- const prjctStatusLinePath = path58.join(prjctStatusLineDir, "statusline.sh");
29050
- const prjctThemesDir = path58.join(prjctStatusLineDir, "themes");
29051
- const prjctLibDir = path58.join(prjctStatusLineDir, "lib");
29052
- const prjctComponentsDir = path58.join(prjctStatusLineDir, "components");
29053
- const prjctConfigPath = path58.join(prjctStatusLineDir, "config.json");
29054
- const assetsDir = path58.join(PACKAGE_ROOT, "assets", "statusline");
29055
- const sourceScript = path58.join(assetsDir, "statusline.sh");
29056
- const sourceThemeDir = path58.join(assetsDir, "themes");
29057
- const sourceLibDir = path58.join(assetsDir, "lib");
29058
- const sourceComponentsDir = path58.join(assetsDir, "components");
29059
- const sourceConfigPath = path58.join(assetsDir, "default-config.json");
29569
+ const claudeDir = path60.join(os18.homedir(), ".claude");
29570
+ const settingsPath = path60.join(claudeDir, "settings.json");
29571
+ const claudeStatusLinePath = path60.join(claudeDir, "prjct-statusline.sh");
29572
+ const prjctStatusLineDir = path60.join(os18.homedir(), ".prjct-cli", "statusline");
29573
+ const prjctStatusLinePath = path60.join(prjctStatusLineDir, "statusline.sh");
29574
+ const prjctThemesDir = path60.join(prjctStatusLineDir, "themes");
29575
+ const prjctLibDir = path60.join(prjctStatusLineDir, "lib");
29576
+ const prjctComponentsDir = path60.join(prjctStatusLineDir, "components");
29577
+ const prjctConfigPath = path60.join(prjctStatusLineDir, "config.json");
29578
+ const assetsDir = path60.join(PACKAGE_ROOT, "assets", "statusline");
29579
+ const sourceScript = path60.join(assetsDir, "statusline.sh");
29580
+ const sourceThemeDir = path60.join(assetsDir, "themes");
29581
+ const sourceLibDir = path60.join(assetsDir, "lib");
29582
+ const sourceComponentsDir = path60.join(assetsDir, "components");
29583
+ const sourceConfigPath = path60.join(assetsDir, "default-config.json");
29060
29584
  if (!await fileExists(claudeDir)) {
29061
- await fs54.mkdir(claudeDir, { recursive: true });
29585
+ await fs56.mkdir(claudeDir, { recursive: true });
29062
29586
  }
29063
29587
  if (!await fileExists(prjctStatusLineDir)) {
29064
- await fs54.mkdir(prjctStatusLineDir, { recursive: true });
29588
+ await fs56.mkdir(prjctStatusLineDir, { recursive: true });
29065
29589
  }
29066
29590
  if (!await fileExists(prjctThemesDir)) {
29067
- await fs54.mkdir(prjctThemesDir, { recursive: true });
29591
+ await fs56.mkdir(prjctThemesDir, { recursive: true });
29068
29592
  }
29069
29593
  if (!await fileExists(prjctLibDir)) {
29070
- await fs54.mkdir(prjctLibDir, { recursive: true });
29594
+ await fs56.mkdir(prjctLibDir, { recursive: true });
29071
29595
  }
29072
29596
  if (!await fileExists(prjctComponentsDir)) {
29073
- await fs54.mkdir(prjctComponentsDir, { recursive: true });
29597
+ await fs56.mkdir(prjctComponentsDir, { recursive: true });
29074
29598
  }
29075
29599
  if (await fileExists(prjctStatusLinePath)) {
29076
- const existingContent = await fs54.readFile(prjctStatusLinePath, "utf8");
29600
+ const existingContent = await fs56.readFile(prjctStatusLinePath, "utf8");
29077
29601
  if (existingContent.includes("CLI_VERSION=")) {
29078
29602
  const versionMatch = existingContent.match(/CLI_VERSION="([^"]*)"/);
29079
29603
  if (versionMatch && versionMatch[1] !== VERSION) {
@@ -29081,7 +29605,7 @@ async function installStatusLine() {
29081
29605
  /CLI_VERSION="[^"]*"/,
29082
29606
  `CLI_VERSION="${VERSION}"`
29083
29607
  );
29084
- await fs54.writeFile(prjctStatusLinePath, updatedContent, { mode: 493 });
29608
+ await fs56.writeFile(prjctStatusLinePath, updatedContent, { mode: 493 });
29085
29609
  }
29086
29610
  await installStatusLineModules(sourceLibDir, prjctLibDir);
29087
29611
  await installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
@@ -29091,21 +29615,21 @@ async function installStatusLine() {
29091
29615
  }
29092
29616
  }
29093
29617
  if (await fileExists(sourceScript)) {
29094
- let scriptContent = await fs54.readFile(sourceScript, "utf8");
29618
+ let scriptContent = await fs56.readFile(sourceScript, "utf8");
29095
29619
  scriptContent = scriptContent.replace(/CLI_VERSION="[^"]*"/, `CLI_VERSION="${VERSION}"`);
29096
- await fs54.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
29620
+ await fs56.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
29097
29621
  await installStatusLineModules(sourceLibDir, prjctLibDir);
29098
29622
  await installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
29099
29623
  if (await fileExists(sourceThemeDir)) {
29100
- const themes = await fs54.readdir(sourceThemeDir);
29624
+ const themes = await fs56.readdir(sourceThemeDir);
29101
29625
  for (const theme of themes) {
29102
- const src = path58.join(sourceThemeDir, theme);
29103
- const dest = path58.join(prjctThemesDir, theme);
29104
- await fs54.copyFile(src, dest);
29626
+ const src = path60.join(sourceThemeDir, theme);
29627
+ const dest = path60.join(prjctThemesDir, theme);
29628
+ await fs56.copyFile(src, dest);
29105
29629
  }
29106
29630
  }
29107
29631
  if (!await fileExists(prjctConfigPath) && await fileExists(sourceConfigPath)) {
29108
- await fs54.copyFile(sourceConfigPath, prjctConfigPath);
29632
+ await fs56.copyFile(sourceConfigPath, prjctConfigPath);
29109
29633
  }
29110
29634
  } else {
29111
29635
  const scriptContent = `#!/bin/bash
@@ -29140,7 +29664,7 @@ if [ -f "$CONFIG" ]; then
29140
29664
  fi
29141
29665
  echo "prjct"
29142
29666
  `;
29143
- await fs54.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
29667
+ await fs56.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
29144
29668
  }
29145
29669
  await ensureStatusLineSymlink(claudeStatusLinePath, prjctStatusLinePath);
29146
29670
  await ensureStatusLineSettings(settingsPath, claudeStatusLinePath);
@@ -29152,10 +29676,10 @@ echo "prjct"
29152
29676
  }
29153
29677
  async function installContext7MCP() {
29154
29678
  try {
29155
- const claudeDir = path58.join(os18.homedir(), ".claude");
29156
- const mcpConfigPath = path58.join(claudeDir, "mcp.json");
29679
+ const claudeDir = path60.join(os18.homedir(), ".claude");
29680
+ const mcpConfigPath = path60.join(claudeDir, "mcp.json");
29157
29681
  if (!await fileExists(claudeDir)) {
29158
- await fs54.mkdir(claudeDir, { recursive: true });
29682
+ await fs56.mkdir(claudeDir, { recursive: true });
29159
29683
  }
29160
29684
  const context7Config = {
29161
29685
  mcpServers: {
@@ -29166,16 +29690,16 @@ async function installContext7MCP() {
29166
29690
  }
29167
29691
  };
29168
29692
  if (await fileExists(mcpConfigPath)) {
29169
- const existingContent = await fs54.readFile(mcpConfigPath, "utf-8");
29693
+ const existingContent = await fs56.readFile(mcpConfigPath, "utf-8");
29170
29694
  const existingConfig = JSON.parse(existingContent);
29171
29695
  if (existingConfig.mcpServers?.context7) {
29172
29696
  return;
29173
29697
  }
29174
29698
  existingConfig.mcpServers = existingConfig.mcpServers || {};
29175
29699
  existingConfig.mcpServers.context7 = context7Config.mcpServers.context7;
29176
- await fs54.writeFile(mcpConfigPath, JSON.stringify(existingConfig, null, 2), "utf-8");
29700
+ await fs56.writeFile(mcpConfigPath, JSON.stringify(existingConfig, null, 2), "utf-8");
29177
29701
  } else {
29178
- await fs54.writeFile(mcpConfigPath, JSON.stringify(context7Config, null, 2), "utf-8");
29702
+ await fs56.writeFile(mcpConfigPath, JSON.stringify(context7Config, null, 2), "utf-8");
29179
29703
  }
29180
29704
  } catch (error) {
29181
29705
  logger_default.warn(`Context7 MCP setup warning: ${getErrorMessage2(error)}`);
@@ -29185,34 +29709,34 @@ async function installStatusLineModules(sourceDir, destDir) {
29185
29709
  if (!await fileExists(sourceDir)) {
29186
29710
  return;
29187
29711
  }
29188
- const files = await fs54.readdir(sourceDir);
29712
+ const files = await fs56.readdir(sourceDir);
29189
29713
  for (const file of files) {
29190
29714
  if (file.endsWith(".sh")) {
29191
- const src = path58.join(sourceDir, file);
29192
- const dest = path58.join(destDir, file);
29193
- await fs54.copyFile(src, dest);
29194
- await fs54.chmod(dest, 493);
29715
+ const src = path60.join(sourceDir, file);
29716
+ const dest = path60.join(destDir, file);
29717
+ await fs56.copyFile(src, dest);
29718
+ await fs56.chmod(dest, 493);
29195
29719
  }
29196
29720
  }
29197
29721
  }
29198
29722
  async function ensureStatusLineSymlink(linkPath, targetPath) {
29199
29723
  try {
29200
29724
  if (await fileExists(linkPath)) {
29201
- const stats = await fs54.lstat(linkPath);
29725
+ const stats = await fs56.lstat(linkPath);
29202
29726
  if (stats.isSymbolicLink()) {
29203
- const existingTarget = await fs54.readlink(linkPath);
29727
+ const existingTarget = await fs56.readlink(linkPath);
29204
29728
  if (existingTarget === targetPath) {
29205
29729
  return;
29206
29730
  }
29207
29731
  }
29208
- await fs54.unlink(linkPath);
29732
+ await fs56.unlink(linkPath);
29209
29733
  }
29210
- await fs54.symlink(targetPath, linkPath);
29734
+ await fs56.symlink(targetPath, linkPath);
29211
29735
  } catch (_error) {
29212
29736
  try {
29213
29737
  if (await fileExists(targetPath)) {
29214
- await fs54.copyFile(targetPath, linkPath);
29215
- await fs54.chmod(linkPath, 493);
29738
+ await fs56.copyFile(targetPath, linkPath);
29739
+ await fs56.chmod(linkPath, 493);
29216
29740
  }
29217
29741
  } catch (copyError) {
29218
29742
  if (!isNotFoundError(copyError)) {
@@ -29627,7 +30151,7 @@ var init_registry2 = __esm({
29627
30151
  });
29628
30152
 
29629
30153
  // core/commands/analytics.ts
29630
- import path59 from "node:path";
30154
+ import path61 from "node:path";
29631
30155
  var AnalyticsCommands;
29632
30156
  var init_analytics = __esm({
29633
30157
  "core/commands/analytics.ts"() {
@@ -29654,7 +30178,7 @@ var init_analytics = __esm({
29654
30178
  output_default.failWithHint("NO_PROJECT_ID");
29655
30179
  return { success: false, error: "No project ID found" };
29656
30180
  }
29657
- const projectName = path59.basename(projectPath);
30181
+ const projectName = path61.basename(projectPath);
29658
30182
  const currentTask = await stateStorage.getCurrentTask(projectId);
29659
30183
  const queueTasks = await queueStorage.getActiveTasks(projectId);
29660
30184
  const shipped = await shippedStorage.getRecent(projectId, 5);
@@ -29906,8 +30430,8 @@ ${"\u2550".repeat(50)}
29906
30430
  });
29907
30431
 
29908
30432
  // core/commands/context.ts
29909
- import fs55 from "node:fs/promises";
29910
- import path60 from "node:path";
30433
+ import fs57 from "node:fs/promises";
30434
+ import path62 from "node:path";
29911
30435
  var ContextCommands, contextCommands;
29912
30436
  var init_context = __esm({
29913
30437
  "core/commands/context.ts"() {
@@ -30033,8 +30557,8 @@ var init_context = __esm({
30033
30557
  */
30034
30558
  async loadRepoAnalysis(globalPath) {
30035
30559
  try {
30036
- const analysisPath = path60.join(globalPath, "analysis", "repo-analysis.json");
30037
- const content = await fs55.readFile(analysisPath, "utf-8");
30560
+ const analysisPath = path62.join(globalPath, "analysis", "repo-analysis.json");
30561
+ const content = await fs57.readFile(analysisPath, "utf-8");
30038
30562
  const data = JSON.parse(content);
30039
30563
  return {
30040
30564
  ecosystem: data.ecosystem || "unknown",
@@ -30053,7 +30577,7 @@ var init_context = __esm({
30053
30577
  });
30054
30578
 
30055
30579
  // core/commands/cleanup.ts
30056
- import path61 from "node:path";
30580
+ import path63 from "node:path";
30057
30581
  async function cleanupMemory(projectPath) {
30058
30582
  const projectId = await config_manager_default.getProjectId(projectPath);
30059
30583
  const results = { rotated: [], totalSize: 0, freedSpace: 0 };
@@ -30069,7 +30593,7 @@ async function cleanupMemory(projectPath) {
30069
30593
  results.totalSize += sizeMB;
30070
30594
  const rotated = await jsonl_helper_exports.rotateJsonLinesIfNeeded(filePath, 10);
30071
30595
  if (rotated) {
30072
- results.rotated.push(path61.basename(filePath));
30596
+ results.rotated.push(path63.basename(filePath));
30073
30597
  results.freedSpace += sizeMB;
30074
30598
  }
30075
30599
  }
@@ -30176,7 +30700,7 @@ var init_cleanup = __esm({
30176
30700
  });
30177
30701
 
30178
30702
  // core/commands/design.ts
30179
- import path62 from "node:path";
30703
+ import path64 from "node:path";
30180
30704
  async function design(target = null, options = {}, projectPath = process.cwd()) {
30181
30705
  try {
30182
30706
  const designType = options.type || "architecture";
@@ -30188,7 +30712,7 @@ async function design(target = null, options = {}, projectPath = process.cwd())
30188
30712
  const designTarget = target || "system";
30189
30713
  output_default.spin(`designing ${designType}...`);
30190
30714
  const projectId = await config_manager_default.getProjectId(projectPath);
30191
- const designsPath = path62.join(
30715
+ const designsPath = path64.join(
30192
30716
  path_manager_default.getGlobalProjectPath(projectId),
30193
30717
  "planning",
30194
30718
  "designs"
@@ -30228,7 +30752,7 @@ async function design(target = null, options = {}, projectPath = process.cwd())
30228
30752
  break;
30229
30753
  }
30230
30754
  const designFileName = `${designType}-${designTarget.toLowerCase().replace(/\s+/g, "-")}.md`;
30231
- const designFilePath = path62.join(designsPath, designFileName);
30755
+ const designFilePath = path64.join(designsPath, designFileName);
30232
30756
  await file_helper_exports.writeFile(designFilePath, designContent);
30233
30757
  await memoryService.log(projectPath, "design_created", {
30234
30758
  type: designType,
@@ -30253,7 +30777,7 @@ var init_design = __esm({
30253
30777
  });
30254
30778
 
30255
30779
  // core/commands/snapshots.ts
30256
- import path63 from "node:path";
30780
+ import path65 from "node:path";
30257
30781
  async function recover(projectPath = process.cwd()) {
30258
30782
  try {
30259
30783
  const projectId = await config_manager_default.getProjectId(projectPath);
@@ -30305,7 +30829,7 @@ async function undo(projectPath = process.cwd()) {
30305
30829
  output_default.failWithHint("NO_PROJECT_ID");
30306
30830
  return { success: false, error: "No project ID found" };
30307
30831
  }
30308
- const snapshotsPath = path63.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
30832
+ const snapshotsPath = path65.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
30309
30833
  await file_helper_exports.ensureDir(snapshotsPath);
30310
30834
  const { execSync: execSync5 } = await import("node:child_process");
30311
30835
  try {
@@ -30323,7 +30847,7 @@ async function undo(projectPath = process.cwd()) {
30323
30847
  cwd: projectPath,
30324
30848
  encoding: "utf-8"
30325
30849
  });
30326
- const snapshotFile = path63.join(snapshotsPath, "history.json");
30850
+ const snapshotFile = path65.join(snapshotsPath, "history.json");
30327
30851
  let history2 = { snapshots: [], current: -1 };
30328
30852
  try {
30329
30853
  const content = await file_helper_exports.readFile(snapshotFile);
@@ -30363,8 +30887,8 @@ async function redo(projectPath = process.cwd()) {
30363
30887
  output_default.failWithHint("NO_PROJECT_ID");
30364
30888
  return { success: false, error: "No project ID found" };
30365
30889
  }
30366
- const snapshotsPath = path63.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
30367
- const snapshotFile = path63.join(snapshotsPath, "history.json");
30890
+ const snapshotsPath = path65.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
30891
+ const snapshotFile = path65.join(snapshotsPath, "history.json");
30368
30892
  let history2;
30369
30893
  try {
30370
30894
  const content = await file_helper_exports.readFile(snapshotFile);
@@ -30423,8 +30947,8 @@ async function history(projectPath = process.cwd()) {
30423
30947
  output_default.failWithHint("NO_PROJECT_ID");
30424
30948
  return { success: false, error: "No project ID found" };
30425
30949
  }
30426
- const snapshotsPath = path63.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
30427
- const snapshotFile = path63.join(snapshotsPath, "history.json");
30950
+ const snapshotsPath = path65.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
30951
+ const snapshotFile = path65.join(snapshotsPath, "history.json");
30428
30952
  let snapshotHistory;
30429
30953
  try {
30430
30954
  const content = await file_helper_exports.readFile(snapshotFile);
@@ -30627,8 +31151,8 @@ ${chalk16.cyan("Performance Report")} ${chalk16.dim(`(last ${days} days)`)}`);
30627
31151
  });
30628
31152
 
30629
31153
  // core/commands/setup.ts
30630
- import fs56 from "node:fs/promises";
30631
- import path64 from "node:path";
31154
+ import fs58 from "node:fs/promises";
31155
+ import path66 from "node:path";
30632
31156
  import chalk17 from "chalk";
30633
31157
  var SetupCommands;
30634
31158
  var init_setup2 = __esm({
@@ -30757,7 +31281,7 @@ Please install it first:
30757
31281
  try {
30758
31282
  const claudeDir = path_manager_default.getClaudeDir();
30759
31283
  const settingsPath = path_manager_default.getClaudeSettingsPath();
30760
- const statusLinePath = path64.join(claudeDir, "prjct-statusline.sh");
31284
+ const statusLinePath = path66.join(claudeDir, "prjct-statusline.sh");
30761
31285
  const scriptContent = `#!/bin/bash
30762
31286
  # prjct Status Line for Claude Code
30763
31287
  # Shows version update notifications and current task
@@ -30815,11 +31339,11 @@ fi
30815
31339
  # Default: show prjct branding
30816
31340
  echo "\u26A1 prjct"
30817
31341
  `;
30818
- await fs56.writeFile(statusLinePath, scriptContent, { mode: 493 });
31342
+ await fs58.writeFile(statusLinePath, scriptContent, { mode: 493 });
30819
31343
  let settings = {};
30820
31344
  if (await fileExists(settingsPath)) {
30821
31345
  try {
30822
- settings = JSON.parse(await fs56.readFile(settingsPath, "utf8"));
31346
+ settings = JSON.parse(await fs58.readFile(settingsPath, "utf8"));
30823
31347
  } catch (_error) {
30824
31348
  }
30825
31349
  }
@@ -30827,7 +31351,7 @@ echo "\u26A1 prjct"
30827
31351
  type: "command",
30828
31352
  command: statusLinePath
30829
31353
  };
30830
- await fs56.writeFile(settingsPath, JSON.stringify(settings, null, 2));
31354
+ await fs58.writeFile(settingsPath, JSON.stringify(settings, null, 2));
30831
31355
  return { success: true };
30832
31356
  } catch (error) {
30833
31357
  return { success: false, error: getErrorMessage2(error) };
@@ -30883,18 +31407,18 @@ echo "\u26A1 prjct"
30883
31407
  });
30884
31408
 
30885
31409
  // core/utils/project-commands.ts
30886
- import path65 from "node:path";
31410
+ import path67 from "node:path";
30887
31411
  async function detectPackageManager(projectPath, pkg) {
30888
31412
  const declared = pkg?.packageManager?.trim().toLowerCase();
30889
31413
  if (declared?.startsWith("pnpm@")) return "pnpm";
30890
31414
  if (declared?.startsWith("yarn@")) return "yarn";
30891
31415
  if (declared?.startsWith("bun@")) return "bun";
30892
31416
  if (declared?.startsWith("npm@")) return "npm";
30893
- if (await fileExists2(path65.join(projectPath, "pnpm-lock.yaml"))) return "pnpm";
30894
- if (await fileExists2(path65.join(projectPath, "yarn.lock"))) return "yarn";
30895
- if (await fileExists2(path65.join(projectPath, "bun.lockb"))) return "bun";
30896
- if (await fileExists2(path65.join(projectPath, "bun.lock"))) return "bun";
30897
- if (await fileExists2(path65.join(projectPath, "package-lock.json"))) return "npm";
31417
+ if (await fileExists2(path67.join(projectPath, "pnpm-lock.yaml"))) return "pnpm";
31418
+ if (await fileExists2(path67.join(projectPath, "yarn.lock"))) return "yarn";
31419
+ if (await fileExists2(path67.join(projectPath, "bun.lockb"))) return "bun";
31420
+ if (await fileExists2(path67.join(projectPath, "bun.lock"))) return "bun";
31421
+ if (await fileExists2(path67.join(projectPath, "package-lock.json"))) return "npm";
30898
31422
  return "npm";
30899
31423
  }
30900
31424
  function pmRun(pm, scriptName) {
@@ -30910,7 +31434,7 @@ function pmTest(pm) {
30910
31434
  return "npm test";
30911
31435
  }
30912
31436
  async function detectProjectCommands(projectPath) {
30913
- const pkgPath = path65.join(projectPath, "package.json");
31437
+ const pkgPath = path67.join(projectPath, "package.json");
30914
31438
  const pkg = await readJson(pkgPath, null);
30915
31439
  if (pkg) {
30916
31440
  const pm = await detectPackageManager(projectPath, pkg);
@@ -30927,27 +31451,27 @@ async function detectProjectCommands(projectPath) {
30927
31451
  }
30928
31452
  return result;
30929
31453
  }
30930
- if (await fileExists2(path65.join(projectPath, "pytest.ini"))) {
31454
+ if (await fileExists2(path67.join(projectPath, "pytest.ini"))) {
30931
31455
  return { stack: "python", test: { tool: "pytest", command: "pytest" } };
30932
31456
  }
30933
- const pyproject = await readFile(path65.join(projectPath, "pyproject.toml"), "");
31457
+ const pyproject = await readFile(path67.join(projectPath, "pyproject.toml"), "");
30934
31458
  if (pyproject.includes("[tool.pytest") || pyproject.includes("pytest")) {
30935
31459
  return { stack: "python", test: { tool: "pytest", command: "pytest" } };
30936
31460
  }
30937
- if (await fileExists2(path65.join(projectPath, "Cargo.toml"))) {
31461
+ if (await fileExists2(path67.join(projectPath, "Cargo.toml"))) {
30938
31462
  return { stack: "rust", test: { tool: "cargo", command: "cargo test" } };
30939
31463
  }
30940
- if (await fileExists2(path65.join(projectPath, "go.mod"))) {
31464
+ if (await fileExists2(path67.join(projectPath, "go.mod"))) {
30941
31465
  return { stack: "go", test: { tool: "go", command: "go test ./..." } };
30942
31466
  }
30943
31467
  const files = await listFiles(projectPath);
30944
31468
  if (files.some((f) => f.endsWith(".sln") || f.endsWith(".csproj") || f.endsWith(".fsproj"))) {
30945
31469
  return { stack: "dotnet", test: { tool: "dotnet", command: "dotnet test" } };
30946
31470
  }
30947
- if (await fileExists2(path65.join(projectPath, "pom.xml"))) {
31471
+ if (await fileExists2(path67.join(projectPath, "pom.xml"))) {
30948
31472
  return { stack: "java", test: { tool: "maven", command: "mvn test" } };
30949
31473
  }
30950
- if (await fileExists2(path65.join(projectPath, "gradlew")) && (await fileExists2(path65.join(projectPath, "build.gradle")) || await fileExists2(path65.join(projectPath, "build.gradle.kts")))) {
31474
+ if (await fileExists2(path67.join(projectPath, "gradlew")) && (await fileExists2(path67.join(projectPath, "build.gradle")) || await fileExists2(path67.join(projectPath, "build.gradle.kts")))) {
30951
31475
  return { stack: "java", test: { tool: "gradle", command: "./gradlew test" } };
30952
31476
  }
30953
31477
  return { stack: "unknown" };
@@ -30964,8 +31488,8 @@ var init_project_commands = __esm({
30964
31488
  });
30965
31489
 
30966
31490
  // core/workflow/workflow-preferences.ts
30967
- import { exec as exec17 } from "node:child_process";
30968
- import { promisify as promisify18 } from "node:util";
31491
+ import { exec as exec18 } from "node:child_process";
31492
+ import { promisify as promisify19 } from "node:util";
30969
31493
  import chalk18 from "chalk";
30970
31494
  function prefKey(hook, command) {
30971
31495
  return `workflow:${hook}_${command}`;
@@ -31108,7 +31632,7 @@ var init_workflow_preferences = __esm({
31108
31632
  init_memory_system();
31109
31633
  init_constants();
31110
31634
  init_fs();
31111
- execAsync12 = promisify18(exec17);
31635
+ execAsync12 = promisify19(exec18);
31112
31636
  sessionPreferences = /* @__PURE__ */ new Map();
31113
31637
  oncePreferences = /* @__PURE__ */ new Map();
31114
31638
  __name(prefKey, "prefKey");
@@ -31122,7 +31646,7 @@ var init_workflow_preferences = __esm({
31122
31646
  });
31123
31647
 
31124
31648
  // core/commands/shipping.ts
31125
- import path66 from "node:path";
31649
+ import path68 from "node:path";
31126
31650
  var ShippingCommands;
31127
31651
  var init_shipping = __esm({
31128
31652
  "core/commands/shipping.ts"() {
@@ -31268,7 +31792,7 @@ ${result.stderr}`.trim();
31268
31792
  */
31269
31793
  async _bumpVersion(projectPath) {
31270
31794
  try {
31271
- const pkgPath = path66.join(projectPath, "package.json");
31795
+ const pkgPath = path68.join(projectPath, "package.json");
31272
31796
  const pkg = await file_helper_exports.readJson(pkgPath, { version: "0.0.0" });
31273
31797
  const oldVersion = pkg?.version || "0.0.0";
31274
31798
  const [major, minor, patch] = oldVersion.split(".").map(Number);
@@ -31290,7 +31814,7 @@ ${result.stderr}`.trim();
31290
31814
  */
31291
31815
  async _updateChangelog(feature, version, projectPath) {
31292
31816
  try {
31293
- const changelogPath = path66.join(projectPath, "CHANGELOG.md");
31817
+ const changelogPath = path68.join(projectPath, "CHANGELOG.md");
31294
31818
  const changelog = await file_helper_exports.readFile(changelogPath, "# Changelog\n\n");
31295
31819
  const entry = `## [${version}] - ${date_helper_exports.formatDate(/* @__PURE__ */ new Date())}
31296
31820
 
@@ -31538,8 +32062,8 @@ var init_cache2 = __esm({
31538
32062
  });
31539
32063
 
31540
32064
  // core/utils/keychain.ts
31541
- import { exec as exec18 } from "node:child_process";
31542
- import { promisify as promisify19 } from "node:util";
32065
+ import { exec as exec19 } from "node:child_process";
32066
+ import { promisify as promisify20 } from "node:util";
31543
32067
  async function getCredential(key) {
31544
32068
  if (process.platform !== "darwin") {
31545
32069
  return getEnvFallback(key);
@@ -31566,7 +32090,7 @@ var init_keychain = __esm({
31566
32090
  "core/utils/keychain.ts"() {
31567
32091
  "use strict";
31568
32092
  init_fs();
31569
- execAsync13 = promisify19(exec18);
32093
+ execAsync13 = promisify20(exec19);
31570
32094
  SERVICE_NAME = "prjct-cli";
31571
32095
  __name(getCredential, "getCredential");
31572
32096
  __name(getEnvFallback, "getEnvFallback");
@@ -32334,11 +32858,11 @@ var init_linear = __esm({
32334
32858
  });
32335
32859
 
32336
32860
  // core/utils/project-credentials.ts
32337
- import fs57 from "node:fs/promises";
32861
+ import fs59 from "node:fs/promises";
32338
32862
  import os19 from "node:os";
32339
- import path67 from "node:path";
32863
+ import path69 from "node:path";
32340
32864
  function getCredentialsPath(projectId) {
32341
- return path67.join(os19.homedir(), ".prjct-cli", "projects", projectId, "config", "credentials.json");
32865
+ return path69.join(os19.homedir(), ".prjct-cli", "projects", projectId, "config", "credentials.json");
32342
32866
  }
32343
32867
  async function getProjectCredentials(projectId) {
32344
32868
  const credPath = getCredentialsPath(projectId);
@@ -32346,7 +32870,7 @@ async function getProjectCredentials(projectId) {
32346
32870
  return {};
32347
32871
  }
32348
32872
  try {
32349
- return JSON.parse(await fs57.readFile(credPath, "utf-8"));
32873
+ return JSON.parse(await fs59.readFile(credPath, "utf-8"));
32350
32874
  } catch (error) {
32351
32875
  console.error("[project-credentials] Failed to read credentials:", getErrorMessage2(error));
32352
32876
  return {};
@@ -33018,7 +33542,7 @@ var require_package = __commonJS({
33018
33542
  "package.json"(exports, module) {
33019
33543
  module.exports = {
33020
33544
  name: "prjct-cli",
33021
- version: "1.16.0",
33545
+ version: "1.17.0",
33022
33546
  description: "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
33023
33547
  main: "core/index.ts",
33024
33548
  bin: {
@@ -33125,7 +33649,7 @@ var require_package = __commonJS({
33125
33649
  // core/index.ts
33126
33650
  var core_exports = {};
33127
33651
  import os20 from "node:os";
33128
- import path68 from "node:path";
33652
+ import path70 from "node:path";
33129
33653
  import chalk20 from "chalk";
33130
33654
  async function main() {
33131
33655
  const [commandName, ...rawArgs] = process.argv.slice(2);
@@ -33338,13 +33862,13 @@ function parseCommandArgs(_cmd, rawArgs) {
33338
33862
  }
33339
33863
  async function displayVersion(version) {
33340
33864
  const detection = await detectAllProviders();
33341
- const claudeCommandPath = path68.join(os20.homedir(), ".claude", "commands", "p.md");
33342
- const geminiCommandPath = path68.join(os20.homedir(), ".gemini", "commands", "p.toml");
33865
+ const claudeCommandPath = path70.join(os20.homedir(), ".claude", "commands", "p.md");
33866
+ const geminiCommandPath = path70.join(os20.homedir(), ".gemini", "commands", "p.toml");
33343
33867
  const [claudeConfigured, geminiConfigured, cursorConfigured, cursorExists] = await Promise.all([
33344
33868
  fileExists(claudeCommandPath),
33345
33869
  fileExists(geminiCommandPath),
33346
- fileExists(path68.join(process.cwd(), ".cursor", "commands", "sync.md")),
33347
- fileExists(path68.join(process.cwd(), ".cursor"))
33870
+ fileExists(path70.join(process.cwd(), ".cursor", "commands", "sync.md")),
33871
+ fileExists(path70.join(process.cwd(), ".cursor"))
33348
33872
  ]);
33349
33873
  const antigravityDetection = await detectAntigravity();
33350
33874
  console.log(`
@@ -33483,7 +34007,7 @@ init_ai_provider();
33483
34007
  init_config_manager();
33484
34008
  init_editors_config();
33485
34009
  import os21 from "node:os";
33486
- import path69 from "node:path";
34010
+ import path71 from "node:path";
33487
34011
  import chalk21 from "chalk";
33488
34012
 
33489
34013
  // core/server/server.ts
@@ -34304,13 +34828,13 @@ async function checkRoutersInstalled() {
34304
34828
  const home = os21.homedir();
34305
34829
  const detection = await detectAllProviders();
34306
34830
  if (detection.claude.installed) {
34307
- const claudeRouter = path69.join(home, ".claude", "commands", "p.md");
34831
+ const claudeRouter = path71.join(home, ".claude", "commands", "p.md");
34308
34832
  if (!await fileExists(claudeRouter)) {
34309
34833
  return false;
34310
34834
  }
34311
34835
  }
34312
34836
  if (detection.gemini.installed) {
34313
- const geminiRouter = path69.join(home, ".gemini", "commands", "p.toml");
34837
+ const geminiRouter = path71.join(home, ".gemini", "commands", "p.toml");
34314
34838
  if (!await fileExists(geminiRouter)) {
34315
34839
  return false;
34316
34840
  }
@@ -34451,7 +34975,7 @@ if (args[0] === "start" || args[0] === "setup") {
34451
34975
  console.error('No prjct project found. Run "prjct init" first.');
34452
34976
  process.exitCode = 1;
34453
34977
  } else {
34454
- const linearCliPath = path69.join(__dirname, "..", "core", "cli", "linear.ts");
34978
+ const linearCliPath = path71.join(__dirname, "..", "core", "cli", "linear.ts");
34455
34979
  const linearArgs = ["--project", projectId, ...args.slice(1)];
34456
34980
  const child = spawn("bun", [linearCliPath, ...linearArgs], {
34457
34981
  stdio: "inherit",
@@ -34478,12 +35002,12 @@ if (args[0] === "start" || args[0] === "setup") {
34478
35002
  windsurfDetected,
34479
35003
  windsurfConfigured
34480
35004
  ] = await Promise.all([
34481
- fileExists(path69.join(home, ".claude", "commands", "p.md")),
34482
- fileExists(path69.join(home, ".gemini", "commands", "p.toml")),
34483
- fileExists(path69.join(cwd, ".cursor")),
34484
- fileExists(path69.join(cwd, ".cursor", "rules", "prjct.mdc")),
34485
- fileExists(path69.join(cwd, ".windsurf")),
34486
- fileExists(path69.join(cwd, ".windsurf", "rules", "prjct.md"))
35005
+ fileExists(path71.join(home, ".claude", "commands", "p.md")),
35006
+ fileExists(path71.join(home, ".gemini", "commands", "p.toml")),
35007
+ fileExists(path71.join(cwd, ".cursor")),
35008
+ fileExists(path71.join(cwd, ".cursor", "rules", "prjct.mdc")),
35009
+ fileExists(path71.join(cwd, ".windsurf")),
35010
+ fileExists(path71.join(cwd, ".windsurf", "rules", "prjct.md"))
34487
35011
  ]);
34488
35012
  console.log(`
34489
35013
  ${chalk21.cyan("p/")} prjct v${VERSION}
@@ -34522,7 +35046,7 @@ ${chalk21.dim("Run 'prjct init' to configure (Cursor/Windsurf IDE)")}
34522
35046
  ${chalk21.cyan("https://prjct.app")}
34523
35047
  `);
34524
35048
  } else {
34525
- const configPath = path69.join(os21.homedir(), ".prjct-cli", "config", "installed-editors.json");
35049
+ const configPath = path71.join(os21.homedir(), ".prjct-cli", "config", "installed-editors.json");
34526
35050
  const routersInstalled = await checkRoutersInstalled();
34527
35051
  if (!await fileExists(configPath) || !routersInstalled) {
34528
35052
  console.log(`