prjct-cli 1.17.0 → 1.18.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) => (path72) => {
20
- var fn = map[path72];
19
+ var __glob = (map) => (path73) => {
20
+ var fn = map[path73];
21
21
  if (fn) return fn();
22
- throw new Error("Module not found in bundle: " + path72);
22
+ throw new Error("Module not found in bundle: " + path73);
23
23
  };
24
24
  var __esm = (fn, res) => function __init() {
25
25
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
@@ -6576,11 +6576,11 @@ async function runSignaturesTool(args2, projectPath) {
6576
6576
  }
6577
6577
  };
6578
6578
  }
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);
6579
+ const fs61 = await import("node:fs/promises");
6580
+ const path73 = await import("node:path");
6581
+ const fullPath = path73.isAbsolute(filePath) ? filePath : path73.join(projectPath, filePath);
6582
6582
  try {
6583
- const stat = await fs60.stat(fullPath);
6583
+ const stat = await fs61.stat(fullPath);
6584
6584
  if (stat.isDirectory()) {
6585
6585
  const results = await extractDirectorySignatures(filePath, projectPath, {
6586
6586
  recursive: args2.includes("--recursive") || args2.includes("-r")
@@ -6647,11 +6647,11 @@ async function runSummaryTool(args2, projectPath) {
6647
6647
  }
6648
6648
  };
6649
6649
  }
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);
6650
+ const fs61 = await import("node:fs/promises");
6651
+ const path73 = await import("node:path");
6652
+ const fullPath = path73.isAbsolute(targetPath) ? targetPath : path73.join(projectPath, targetPath);
6653
6653
  try {
6654
- const stat = await fs60.stat(fullPath);
6654
+ const stat = await fs61.stat(fullPath);
6655
6655
  if (stat.isDirectory()) {
6656
6656
  const results = await summarizeDirectory(targetPath, projectPath, {
6657
6657
  recursive: args2.includes("--recursive") || args2.includes("-r")
@@ -21768,16 +21768,16 @@ var init_onboarding = __esm({
21768
21768
  * Detect project type from file system
21769
21769
  */
21770
21770
  async detectProjectType() {
21771
- const fs60 = await import("node:fs/promises");
21772
- const path72 = await import("node:path");
21771
+ const fs61 = await import("node:fs/promises");
21772
+ const path73 = await import("node:path");
21773
21773
  try {
21774
- const files = await fs60.readdir(this.projectPath);
21774
+ const files = await fs61.readdir(this.projectPath);
21775
21775
  if (files.includes("turbo.json") || files.includes("lerna.json") || files.includes("nx.json")) {
21776
21776
  return "monorepo";
21777
21777
  }
21778
21778
  if (files.includes("package.json")) {
21779
- const pkgPath = path72.join(this.projectPath, "package.json");
21780
- const pkgContent = await fs60.readFile(pkgPath, "utf-8");
21779
+ const pkgPath = path73.join(this.projectPath, "package.json");
21780
+ const pkgContent = await fs61.readFile(pkgPath, "utf-8");
21781
21781
  const pkg = JSON.parse(pkgContent);
21782
21782
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
21783
21783
  if (pkg.bin) return "cli-tool";
@@ -21813,32 +21813,32 @@ var init_onboarding = __esm({
21813
21813
  * Detect installed AI agents from config files
21814
21814
  */
21815
21815
  async detectInstalledAgents() {
21816
- const fs60 = await import("node:fs/promises");
21817
- const path72 = await import("node:path");
21816
+ const fs61 = await import("node:fs/promises");
21817
+ const path73 = await import("node:path");
21818
21818
  const os22 = await import("node:os");
21819
21819
  const agents = [];
21820
21820
  try {
21821
- await fs60.access(path72.join(os22.homedir(), ".claude"));
21821
+ await fs61.access(path73.join(os22.homedir(), ".claude"));
21822
21822
  agents.push("claude");
21823
21823
  } catch {
21824
21824
  }
21825
21825
  try {
21826
- await fs60.access(path72.join(this.projectPath, ".cursorrules"));
21826
+ await fs61.access(path73.join(this.projectPath, ".cursorrules"));
21827
21827
  agents.push("cursor");
21828
21828
  } catch {
21829
21829
  }
21830
21830
  try {
21831
- await fs60.access(path72.join(this.projectPath, ".windsurfrules"));
21831
+ await fs61.access(path73.join(this.projectPath, ".windsurfrules"));
21832
21832
  agents.push("windsurf");
21833
21833
  } catch {
21834
21834
  }
21835
21835
  try {
21836
- await fs60.access(path72.join(this.projectPath, ".github", "copilot-instructions.md"));
21836
+ await fs61.access(path73.join(this.projectPath, ".github", "copilot-instructions.md"));
21837
21837
  agents.push("copilot");
21838
21838
  } catch {
21839
21839
  }
21840
21840
  try {
21841
- await fs60.access(path72.join(os22.homedir(), ".gemini"));
21841
+ await fs61.access(path73.join(os22.homedir(), ".gemini"));
21842
21842
  agents.push("gemini");
21843
21843
  } catch {
21844
21844
  }
@@ -21848,17 +21848,17 @@ var init_onboarding = __esm({
21848
21848
  * Detect tech stack from project files
21849
21849
  */
21850
21850
  async detectStack() {
21851
- const fs60 = await import("node:fs/promises");
21852
- const path72 = await import("node:path");
21851
+ const fs61 = await import("node:fs/promises");
21852
+ const path73 = await import("node:path");
21853
21853
  const stack = {
21854
21854
  language: "Unknown",
21855
21855
  technologies: []
21856
21856
  };
21857
21857
  try {
21858
- const files = await fs60.readdir(this.projectPath);
21858
+ const files = await fs61.readdir(this.projectPath);
21859
21859
  if (files.includes("package.json")) {
21860
- const pkgPath = path72.join(this.projectPath, "package.json");
21861
- const pkgContent = await fs60.readFile(pkgPath, "utf-8");
21860
+ const pkgPath = path73.join(this.projectPath, "package.json");
21861
+ const pkgContent = await fs61.readFile(pkgPath, "utf-8");
21862
21862
  const pkg = JSON.parse(pkgContent);
21863
21863
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
21864
21864
  stack.language = deps.typescript ? "TypeScript" : "JavaScript";
@@ -22984,7 +22984,10 @@ var init_analysis2 = __esm({
22984
22984
  if (!isNonInteractive) {
22985
22985
  output_default.spin("Analyzing changes...");
22986
22986
  }
22987
- const result2 = await syncService.sync(projectPath, { aiTools: options.aiTools });
22987
+ const result2 = await syncService.sync(projectPath, {
22988
+ aiTools: options.aiTools,
22989
+ full: options.full
22990
+ });
22988
22991
  if (!result2.success) {
22989
22992
  if (isNonInteractive) {
22990
22993
  console.log(JSON.stringify({ success: false, error: result2.error || "Sync failed" }));
@@ -23098,7 +23101,10 @@ ${formatFullDiff(diff)}`);
23098
23101
  return this.showSyncResult(result2, startTime);
23099
23102
  }
23100
23103
  output_default.spin("Syncing project...");
23101
- const result = await syncService.sync(projectPath, { aiTools: options.aiTools });
23104
+ const result = await syncService.sync(projectPath, {
23105
+ aiTools: options.aiTools,
23106
+ full: options.full
23107
+ });
23102
23108
  if (!result.success) {
23103
23109
  output_default.fail(result.error || "Sync failed");
23104
23110
  return { success: false, error: result.error };
@@ -24083,8 +24089,8 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
24083
24089
  const globalPath2 = path_manager_default.getGlobalProjectPath(projectId);
24084
24090
  const specsPath2 = path45.join(globalPath2, "planning", "specs");
24085
24091
  try {
24086
- const fs60 = await import("node:fs/promises");
24087
- const files = await fs60.readdir(specsPath2);
24092
+ const fs61 = await import("node:fs/promises");
24093
+ const files = await fs61.readdir(specsPath2);
24088
24094
  const specs = files.filter((f) => f.endsWith(".md") && f !== ".gitkeep");
24089
24095
  if (specs.length === 0) {
24090
24096
  output_default.warn("no specs yet");
@@ -25283,109 +25289,6 @@ var init_bm25 = __esm({
25283
25289
  }
25284
25290
  });
25285
25291
 
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
25292
  // core/domain/import-graph.ts
25390
25293
  import fs47 from "node:fs/promises";
25391
25294
  import path50 from "node:path";
@@ -25483,14 +25386,17 @@ async function buildGraph(projectPath) {
25483
25386
  };
25484
25387
  }
25485
25388
  function saveGraph(projectId, graph) {
25486
- database_default.setDoc(projectId, INDEX_KEY3, graph);
25389
+ database_default.setDoc(projectId, INDEX_KEY2, graph);
25390
+ }
25391
+ function loadGraph(projectId) {
25392
+ return database_default.getDoc(projectId, INDEX_KEY2);
25487
25393
  }
25488
25394
  async function indexImports(projectPath, projectId) {
25489
25395
  const graph = await buildGraph(projectPath);
25490
25396
  saveGraph(projectId, graph);
25491
25397
  return graph;
25492
25398
  }
25493
- var INDEXABLE_EXTENSIONS2, SKIP_DIRS2, RESOLVE_EXTENSIONS, IMPORT_REGEX, INDEX_KEY3;
25399
+ var INDEXABLE_EXTENSIONS2, SKIP_DIRS2, RESOLVE_EXTENSIONS, IMPORT_REGEX, INDEX_KEY2;
25494
25400
  var init_import_graph = __esm({
25495
25401
  "core/domain/import-graph.ts"() {
25496
25402
  "use strict";
@@ -25514,15 +25420,362 @@ var init_import_graph = __esm({
25514
25420
  __name(resolveImport2, "resolveImport");
25515
25421
  __name(listFiles3, "listFiles");
25516
25422
  __name(buildGraph, "buildGraph");
25517
- INDEX_KEY3 = "import-graph";
25423
+ INDEX_KEY2 = "import-graph";
25518
25424
  __name(saveGraph, "saveGraph");
25425
+ __name(loadGraph, "loadGraph");
25519
25426
  __name(indexImports, "indexImports");
25520
25427
  }
25521
25428
  });
25522
25429
 
25523
- // core/services/context-generator.ts
25430
+ // core/domain/change-propagator.ts
25431
+ function propagateChanges(diff, projectId) {
25432
+ const directlyChanged = [...diff.added, ...diff.modified];
25433
+ const directSet = new Set(directlyChanged);
25434
+ const affected = /* @__PURE__ */ new Set();
25435
+ const graph = loadGraph(projectId);
25436
+ if (graph) {
25437
+ for (const changedFile of directlyChanged) {
25438
+ const importers = graph.reverse[changedFile];
25439
+ if (importers) {
25440
+ for (const importer of importers) {
25441
+ if (!directSet.has(importer)) {
25442
+ affected.add(importer);
25443
+ }
25444
+ }
25445
+ }
25446
+ }
25447
+ }
25448
+ const affectedByImports = Array.from(affected);
25449
+ const allAffected = [...directlyChanged, ...affectedByImports];
25450
+ return {
25451
+ directlyChanged,
25452
+ affectedByImports,
25453
+ deleted: diff.deleted,
25454
+ allAffected
25455
+ };
25456
+ }
25457
+ function affectedDomains(changedFiles) {
25458
+ const domains = /* @__PURE__ */ new Set();
25459
+ for (const file of changedFiles) {
25460
+ const lower = file.toLowerCase();
25461
+ if (lower.endsWith(".tsx") || lower.endsWith(".jsx") || lower.endsWith(".css") || lower.endsWith(".scss") || lower.endsWith(".vue") || lower.endsWith(".svelte") || lower.includes("/components/") || lower.includes("/pages/") || lower.includes("/app/")) {
25462
+ domains.add("frontend");
25463
+ domains.add("uxui");
25464
+ }
25465
+ if (lower.includes(".test.") || lower.includes(".spec.") || lower.includes("__tests__") || lower.includes("/test/")) {
25466
+ domains.add("testing");
25467
+ }
25468
+ if (lower.includes("dockerfile") || lower.includes("docker-compose") || lower.includes(".dockerignore") || lower.includes(".github/") || lower.includes("ci/") || lower.includes("cd/")) {
25469
+ domains.add("devops");
25470
+ }
25471
+ if (lower.endsWith(".sql") || lower.includes("prisma") || lower.includes("drizzle") || lower.includes("migration") || lower.includes("/db/")) {
25472
+ domains.add("database");
25473
+ }
25474
+ if ((lower.endsWith(".ts") || lower.endsWith(".js")) && !lower.includes(".test.") && !lower.includes(".spec.") && !lower.endsWith(".d.ts")) {
25475
+ domains.add("backend");
25476
+ }
25477
+ }
25478
+ return domains;
25479
+ }
25480
+ var init_change_propagator = __esm({
25481
+ "core/domain/change-propagator.ts"() {
25482
+ "use strict";
25483
+ init_import_graph();
25484
+ __name(propagateChanges, "propagateChanges");
25485
+ __name(affectedDomains, "affectedDomains");
25486
+ }
25487
+ });
25488
+
25489
+ // core/domain/file-hasher.ts
25524
25490
  import fs48 from "node:fs/promises";
25525
25491
  import path51 from "node:path";
25492
+ async function listProjectFiles(dir, projectPath) {
25493
+ const files = [];
25494
+ const entries = await fs48.readdir(dir, { withFileTypes: true }).catch(() => []);
25495
+ for (const entry of entries) {
25496
+ const name = String(entry.name);
25497
+ if (SKIP_DIRS3.has(name)) continue;
25498
+ if (name.startsWith(".") && name !== ".env.example") continue;
25499
+ const fullPath = path51.join(dir, name);
25500
+ if (entry.isDirectory()) {
25501
+ files.push(...await listProjectFiles(fullPath, projectPath));
25502
+ } else if (entry.isFile()) {
25503
+ const ext = path51.extname(name).toLowerCase();
25504
+ if (INDEXABLE_EXTENSIONS3.has(ext)) {
25505
+ files.push(path51.relative(projectPath, fullPath));
25506
+ }
25507
+ }
25508
+ }
25509
+ return files;
25510
+ }
25511
+ function hashContent(content) {
25512
+ if (typeof Bun !== "undefined" && Bun.hash) {
25513
+ return `xxh64:${Bun.hash(content).toString(36)}`;
25514
+ }
25515
+ let h = 2166136261;
25516
+ for (let i = 0; i < content.length; i++) {
25517
+ h ^= content.charCodeAt(i);
25518
+ h = Math.imul(h, 16777619);
25519
+ }
25520
+ return `fnv1a:${(h >>> 0).toString(36)}`;
25521
+ }
25522
+ async function computeHashes(projectPath) {
25523
+ const filePaths = await listProjectFiles(projectPath, projectPath);
25524
+ const hashes = /* @__PURE__ */ new Map();
25525
+ const BATCH_SIZE = 100;
25526
+ for (let i = 0; i < filePaths.length; i += BATCH_SIZE) {
25527
+ const batch = filePaths.slice(i, i + BATCH_SIZE);
25528
+ const results = await Promise.all(
25529
+ batch.map(async (filePath) => {
25530
+ try {
25531
+ const fullPath = path51.join(projectPath, filePath);
25532
+ const [content, stat] = await Promise.all([
25533
+ fs48.readFile(fullPath, "utf-8"),
25534
+ fs48.stat(fullPath)
25535
+ ]);
25536
+ return {
25537
+ path: filePath,
25538
+ hash: hashContent(content),
25539
+ size: stat.size,
25540
+ mtime: stat.mtime.toISOString()
25541
+ };
25542
+ } catch {
25543
+ return null;
25544
+ }
25545
+ })
25546
+ );
25547
+ for (const result of results) {
25548
+ if (result) {
25549
+ hashes.set(result.path, result);
25550
+ }
25551
+ }
25552
+ }
25553
+ return hashes;
25554
+ }
25555
+ function diffHashes(current, stored) {
25556
+ const added = [];
25557
+ const modified = [];
25558
+ const unchanged = [];
25559
+ for (const [filePath, currentHash] of current) {
25560
+ const storedHash = stored.get(filePath);
25561
+ if (!storedHash) {
25562
+ added.push(filePath);
25563
+ } else if (storedHash.hash !== currentHash.hash) {
25564
+ modified.push(filePath);
25565
+ } else {
25566
+ unchanged.push(filePath);
25567
+ }
25568
+ }
25569
+ const deleted = [];
25570
+ for (const filePath of stored.keys()) {
25571
+ if (!current.has(filePath)) {
25572
+ deleted.push(filePath);
25573
+ }
25574
+ }
25575
+ return { added, modified, deleted, unchanged };
25576
+ }
25577
+ function saveHashes(projectId, hashes) {
25578
+ const db = database_default.getDb(projectId);
25579
+ db.transaction(() => {
25580
+ db.prepare("DELETE FROM index_checksums").run();
25581
+ const insert = db.prepare(
25582
+ "INSERT INTO index_checksums (path, checksum, size, mtime) VALUES (?, ?, ?, ?)"
25583
+ );
25584
+ for (const [, hash] of hashes) {
25585
+ insert.run(hash.path, hash.hash, hash.size, hash.mtime);
25586
+ }
25587
+ })();
25588
+ database_default.setDoc(projectId, "file-hashes-meta", {
25589
+ fileCount: hashes.size,
25590
+ builtAt: (/* @__PURE__ */ new Date()).toISOString()
25591
+ });
25592
+ }
25593
+ function loadHashes(projectId) {
25594
+ const hashes = /* @__PURE__ */ new Map();
25595
+ try {
25596
+ const rows = database_default.query(
25597
+ projectId,
25598
+ "SELECT path, checksum, size, mtime FROM index_checksums"
25599
+ );
25600
+ for (const row of rows) {
25601
+ hashes.set(row.path, {
25602
+ path: row.path,
25603
+ hash: row.checksum,
25604
+ size: row.size || 0,
25605
+ mtime: row.mtime || ""
25606
+ });
25607
+ }
25608
+ } catch {
25609
+ }
25610
+ return hashes;
25611
+ }
25612
+ async function detectChanges(projectPath, projectId) {
25613
+ const [currentHashes, storedHashes] = await Promise.all([
25614
+ computeHashes(projectPath),
25615
+ Promise.resolve(loadHashes(projectId))
25616
+ ]);
25617
+ const diff = diffHashes(currentHashes, storedHashes);
25618
+ return { diff, currentHashes };
25619
+ }
25620
+ function hasHashRegistry(projectId) {
25621
+ return database_default.hasDoc(projectId, "file-hashes-meta");
25622
+ }
25623
+ var INDEXABLE_EXTENSIONS3, SKIP_DIRS3;
25624
+ var init_file_hasher = __esm({
25625
+ "core/domain/file-hasher.ts"() {
25626
+ "use strict";
25627
+ init_database();
25628
+ INDEXABLE_EXTENSIONS3 = /* @__PURE__ */ new Set([
25629
+ ".ts",
25630
+ ".tsx",
25631
+ ".js",
25632
+ ".jsx",
25633
+ ".mjs",
25634
+ ".cjs",
25635
+ ".json",
25636
+ ".md",
25637
+ ".css",
25638
+ ".scss",
25639
+ ".html",
25640
+ ".vue",
25641
+ ".svelte",
25642
+ ".py",
25643
+ ".go",
25644
+ ".rs",
25645
+ ".yaml",
25646
+ ".yml",
25647
+ ".toml"
25648
+ ]);
25649
+ SKIP_DIRS3 = /* @__PURE__ */ new Set([
25650
+ "node_modules",
25651
+ ".git",
25652
+ "dist",
25653
+ "build",
25654
+ "out",
25655
+ ".next",
25656
+ "coverage",
25657
+ ".cache",
25658
+ ".turbo",
25659
+ ".vercel",
25660
+ ".prjct"
25661
+ ]);
25662
+ __name(listProjectFiles, "listProjectFiles");
25663
+ __name(hashContent, "hashContent");
25664
+ __name(computeHashes, "computeHashes");
25665
+ __name(diffHashes, "diffHashes");
25666
+ __name(saveHashes, "saveHashes");
25667
+ __name(loadHashes, "loadHashes");
25668
+ __name(detectChanges, "detectChanges");
25669
+ __name(hasHashRegistry, "hasHashRegistry");
25670
+ }
25671
+ });
25672
+
25673
+ // core/domain/git-cochange.ts
25674
+ import { exec as execCallback7 } from "node:child_process";
25675
+ import { promisify as promisify15 } from "node:util";
25676
+ async function parseGitLog(projectPath, maxCommits = 100) {
25677
+ try {
25678
+ const { stdout } = await exec14(
25679
+ `git log --name-only --pretty=format:'---COMMIT---' -${maxCommits}`,
25680
+ { cwd: projectPath, maxBuffer: 10 * 1024 * 1024 }
25681
+ );
25682
+ const commits = [];
25683
+ let currentFiles = null;
25684
+ for (const line of stdout.split("\n")) {
25685
+ const trimmed = line.trim();
25686
+ if (trimmed === "---COMMIT---") {
25687
+ if (currentFiles && currentFiles.size > 0 && currentFiles.size <= MAX_FILES_PER_COMMIT) {
25688
+ commits.push(currentFiles);
25689
+ }
25690
+ currentFiles = /* @__PURE__ */ new Set();
25691
+ } else if (trimmed && currentFiles) {
25692
+ if (isSourceFile(trimmed)) {
25693
+ currentFiles.add(trimmed);
25694
+ }
25695
+ }
25696
+ }
25697
+ if (currentFiles && currentFiles.size > 0 && currentFiles.size <= MAX_FILES_PER_COMMIT) {
25698
+ commits.push(currentFiles);
25699
+ }
25700
+ return commits;
25701
+ } catch {
25702
+ return [];
25703
+ }
25704
+ }
25705
+ function isSourceFile(filePath) {
25706
+ const sourceExtensions = /\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|cs|rb|php|vue|svelte)$/i;
25707
+ return sourceExtensions.test(filePath) && !filePath.includes("node_modules/");
25708
+ }
25709
+ async function buildMatrix(projectPath, maxCommits = 100) {
25710
+ const commitSets = await parseGitLog(projectPath, maxCommits);
25711
+ const fileCommitCount = /* @__PURE__ */ new Map();
25712
+ const pairCount = /* @__PURE__ */ new Map();
25713
+ for (const files of commitSets) {
25714
+ const fileArray = Array.from(files);
25715
+ for (const file of fileArray) {
25716
+ fileCommitCount.set(file, (fileCommitCount.get(file) || 0) + 1);
25717
+ }
25718
+ for (let i = 0; i < fileArray.length; i++) {
25719
+ for (let j = i + 1; j < fileArray.length; j++) {
25720
+ const key = pairKey(fileArray[i], fileArray[j]);
25721
+ pairCount.set(key, (pairCount.get(key) || 0) + 1);
25722
+ }
25723
+ }
25724
+ }
25725
+ const matrix = {};
25726
+ for (const [key, count] of pairCount) {
25727
+ const [fileA, fileB] = key.split("\0");
25728
+ const countA = fileCommitCount.get(fileA) || 0;
25729
+ const countB = fileCommitCount.get(fileB) || 0;
25730
+ if (countA < MIN_FILE_OCCURRENCES || countB < MIN_FILE_OCCURRENCES) continue;
25731
+ const unionCount = countA + countB - count;
25732
+ const similarity = unionCount > 0 ? count / unionCount : 0;
25733
+ if (similarity < MIN_SIMILARITY) continue;
25734
+ if (!matrix[fileA]) matrix[fileA] = {};
25735
+ if (!matrix[fileB]) matrix[fileB] = {};
25736
+ matrix[fileA][fileB] = similarity;
25737
+ matrix[fileB][fileA] = similarity;
25738
+ }
25739
+ return {
25740
+ matrix,
25741
+ commitsAnalyzed: commitSets.length,
25742
+ filesAnalyzed: fileCommitCount.size,
25743
+ builtAt: (/* @__PURE__ */ new Date()).toISOString()
25744
+ };
25745
+ }
25746
+ function pairKey(a, b) {
25747
+ return a < b ? `${a}\0${b}` : `${b}\0${a}`;
25748
+ }
25749
+ function saveMatrix(projectId, index) {
25750
+ database_default.setDoc(projectId, INDEX_KEY3, index);
25751
+ }
25752
+ async function indexCoChanges(projectPath, projectId, maxCommits = 100) {
25753
+ const index = await buildMatrix(projectPath, maxCommits);
25754
+ saveMatrix(projectId, index);
25755
+ return index;
25756
+ }
25757
+ var exec14, MIN_SIMILARITY, MIN_FILE_OCCURRENCES, MAX_FILES_PER_COMMIT, INDEX_KEY3;
25758
+ var init_git_cochange = __esm({
25759
+ "core/domain/git-cochange.ts"() {
25760
+ "use strict";
25761
+ init_database();
25762
+ exec14 = promisify15(execCallback7);
25763
+ MIN_SIMILARITY = 0.1;
25764
+ MIN_FILE_OCCURRENCES = 2;
25765
+ MAX_FILES_PER_COMMIT = 30;
25766
+ __name(parseGitLog, "parseGitLog");
25767
+ __name(isSourceFile, "isSourceFile");
25768
+ __name(buildMatrix, "buildMatrix");
25769
+ __name(pairKey, "pairKey");
25770
+ INDEX_KEY3 = "cochange-index";
25771
+ __name(saveMatrix, "saveMatrix");
25772
+ __name(indexCoChanges, "indexCoChanges");
25773
+ }
25774
+ });
25775
+
25776
+ // core/services/context-generator.ts
25777
+ import fs49 from "node:fs/promises";
25778
+ import path52 from "node:path";
25526
25779
  var ContextFileGenerator;
25527
25780
  var init_context_generator = __esm({
25528
25781
  "core/services/context-generator.ts"() {
@@ -25547,10 +25800,10 @@ var init_context_generator = __esm({
25547
25800
  async writeWithPreservation(filePath, content) {
25548
25801
  let finalContent = content;
25549
25802
  try {
25550
- const existingContent = await fs48.readFile(filePath, "utf-8");
25803
+ const existingContent = await fs49.readFile(filePath, "utf-8");
25551
25804
  const validation = validatePreserveBlocks(existingContent);
25552
25805
  if (!validation.valid) {
25553
- const filename = path51.basename(filePath);
25806
+ const filename = path52.basename(filePath);
25554
25807
  console.warn(`\u26A0\uFE0F ${filename} has invalid preserve blocks:`);
25555
25808
  for (const error of validation.errors) {
25556
25809
  console.warn(` ${error}`);
@@ -25559,13 +25812,13 @@ var init_context_generator = __esm({
25559
25812
  finalContent = mergePreservedSections(content, existingContent);
25560
25813
  } catch {
25561
25814
  }
25562
- await fs48.writeFile(filePath, finalContent, "utf-8");
25815
+ await fs49.writeFile(filePath, finalContent, "utf-8");
25563
25816
  }
25564
25817
  /**
25565
25818
  * Generate all context files in parallel
25566
25819
  */
25567
25820
  async generate(git, stats, commands, agents, sources) {
25568
- const contextPath = path51.join(this.config.globalPath, "context");
25821
+ const contextPath = path52.join(this.config.globalPath, "context");
25569
25822
  await Promise.all([
25570
25823
  this.generateClaudeMd(contextPath, git, stats, commands, agents, sources),
25571
25824
  this.generateNowMd(contextPath),
@@ -25665,7 +25918,7 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
25665
25918
  **Workflow**: ${workflowAgents.join(", ")}
25666
25919
  **Domain**: ${domainAgents.join(", ") || "none"}
25667
25920
  `;
25668
- const claudePath = path51.join(contextPath, "CLAUDE.md");
25921
+ const claudePath = path52.join(contextPath, "CLAUDE.md");
25669
25922
  await this.writeWithPreservation(claudePath, content);
25670
25923
  }
25671
25924
  /**
@@ -25674,8 +25927,8 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
25674
25927
  async generateNowMd(contextPath) {
25675
25928
  let currentTask = null;
25676
25929
  try {
25677
- const statePath = path51.join(this.config.globalPath, "storage", "state.json");
25678
- const state = JSON.parse(await fs48.readFile(statePath, "utf-8"));
25930
+ const statePath = path52.join(this.config.globalPath, "storage", "state.json");
25931
+ const state = JSON.parse(await fs49.readFile(statePath, "utf-8"));
25679
25932
  currentTask = state.currentTask;
25680
25933
  } catch {
25681
25934
  }
@@ -25691,7 +25944,7 @@ _No active task_
25691
25944
 
25692
25945
  Use \`p. task "description"\` to start working.
25693
25946
  `;
25694
- await this.writeWithPreservation(path51.join(contextPath, "now.md"), content);
25947
+ await this.writeWithPreservation(path52.join(contextPath, "now.md"), content);
25695
25948
  }
25696
25949
  /**
25697
25950
  * Generate next.md - task queue
@@ -25699,15 +25952,15 @@ Use \`p. task "description"\` to start working.
25699
25952
  async generateNextMd(contextPath) {
25700
25953
  let queue = { tasks: [] };
25701
25954
  try {
25702
- const queuePath = path51.join(this.config.globalPath, "storage", "queue.json");
25703
- queue = JSON.parse(await fs48.readFile(queuePath, "utf-8"));
25955
+ const queuePath = path52.join(this.config.globalPath, "storage", "queue.json");
25956
+ queue = JSON.parse(await fs49.readFile(queuePath, "utf-8"));
25704
25957
  } catch {
25705
25958
  }
25706
25959
  const content = `# NEXT
25707
25960
 
25708
25961
  ${queue.tasks.length > 0 ? queue.tasks.map((t, i) => `${i + 1}. ${t.description}${t.priority ? ` [${t.priority}]` : ""}`).join("\n") : "_Empty queue_"}
25709
25962
  `;
25710
- await this.writeWithPreservation(path51.join(contextPath, "next.md"), content);
25963
+ await this.writeWithPreservation(path52.join(contextPath, "next.md"), content);
25711
25964
  }
25712
25965
  /**
25713
25966
  * Generate ideas.md - captured ideas
@@ -25715,15 +25968,15 @@ ${queue.tasks.length > 0 ? queue.tasks.map((t, i) => `${i + 1}. ${t.description}
25715
25968
  async generateIdeasMd(contextPath) {
25716
25969
  let ideas = { ideas: [] };
25717
25970
  try {
25718
- const ideasPath = path51.join(this.config.globalPath, "storage", "ideas.json");
25719
- ideas = JSON.parse(await fs48.readFile(ideasPath, "utf-8"));
25971
+ const ideasPath = path52.join(this.config.globalPath, "storage", "ideas.json");
25972
+ ideas = JSON.parse(await fs49.readFile(ideasPath, "utf-8"));
25720
25973
  } catch {
25721
25974
  }
25722
25975
  const content = `# IDEAS
25723
25976
 
25724
25977
  ${ideas.ideas.length > 0 ? ideas.ideas.map((i) => `- ${i.text}${i.priority ? ` [${i.priority}]` : ""}`).join("\n") : "_No ideas captured yet_"}
25725
25978
  `;
25726
- await this.writeWithPreservation(path51.join(contextPath, "ideas.md"), content);
25979
+ await this.writeWithPreservation(path52.join(contextPath, "ideas.md"), content);
25727
25980
  }
25728
25981
  /**
25729
25982
  * Generate shipped.md - completed features
@@ -25733,8 +25986,8 @@ ${ideas.ideas.length > 0 ? ideas.ideas.map((i) => `- ${i.text}${i.priority ? ` [
25733
25986
  shipped: []
25734
25987
  };
25735
25988
  try {
25736
- const shippedPath = path51.join(this.config.globalPath, "storage", "shipped.json");
25737
- shipped = JSON.parse(await fs48.readFile(shippedPath, "utf-8"));
25989
+ const shippedPath = path52.join(this.config.globalPath, "storage", "shipped.json");
25990
+ shipped = JSON.parse(await fs49.readFile(shippedPath, "utf-8"));
25738
25991
  } catch {
25739
25992
  }
25740
25993
  const content = `# SHIPPED \u{1F680}
@@ -25743,7 +25996,7 @@ ${shipped.shipped.length > 0 ? shipped.shipped.slice(-10).map((s) => `- **${s.na
25743
25996
 
25744
25997
  **Total shipped:** ${shipped.shipped.length}
25745
25998
  `;
25746
- await this.writeWithPreservation(path51.join(contextPath, "shipped.md"), content);
25999
+ await this.writeWithPreservation(path52.join(contextPath, "shipped.md"), content);
25747
26000
  }
25748
26001
  // ==========================================================================
25749
26002
  // MONOREPO SUPPORT
@@ -25772,9 +26025,9 @@ ${shipped.shipped.length > 0 ? shipped.shipped.slice(-10).map((s) => `- **${s.na
25772
26025
  commands,
25773
26026
  agents
25774
26027
  );
25775
- const claudePath = path51.join(pkg.path, "CLAUDE.md");
26028
+ const claudePath = path52.join(pkg.path, "CLAUDE.md");
25776
26029
  await this.writeWithPreservation(claudePath, content);
25777
- generatedFiles.push(path51.relative(this.config.projectPath, claudePath));
26030
+ generatedFiles.push(path52.relative(this.config.projectPath, claudePath));
25778
26031
  }
25779
26032
  return generatedFiles;
25780
26033
  }
@@ -25787,8 +26040,8 @@ ${shipped.shipped.length > 0 ? shipped.shipped.slice(-10).map((s) => `- **${s.na
25787
26040
  let pkgVersion = stats.version;
25788
26041
  let pkgName = pkg.name;
25789
26042
  try {
25790
- const pkgJsonPath = path51.join(pkg.path, "package.json");
25791
- const pkgJson = JSON.parse(await fs48.readFile(pkgJsonPath, "utf-8"));
26043
+ const pkgJsonPath = path52.join(pkg.path, "package.json");
26044
+ const pkgJson = JSON.parse(await fs49.readFile(pkgJsonPath, "utf-8"));
25792
26045
  pkgVersion = pkgJson.version || stats.version;
25793
26046
  pkgName = pkgJson.name || pkg.name;
25794
26047
  } catch {
@@ -25853,8 +26106,8 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
25853
26106
  });
25854
26107
 
25855
26108
  // core/services/local-state-generator.ts
25856
- import fs49 from "node:fs/promises";
25857
- import path52 from "node:path";
26109
+ import fs50 from "node:fs/promises";
26110
+ import path53 from "node:path";
25858
26111
  var LOCAL_STATE_FILENAME, LocalStateGenerator, localStateGenerator;
25859
26112
  var init_local_state_generator = __esm({
25860
26113
  "core/services/local-state-generator.ts"() {
@@ -25869,17 +26122,17 @@ var init_local_state_generator = __esm({
25869
26122
  * Generate .prjct-state.md in the project root
25870
26123
  */
25871
26124
  async generate(projectPath, state) {
25872
- const filePath = path52.join(projectPath, LOCAL_STATE_FILENAME);
26125
+ const filePath = path53.join(projectPath, LOCAL_STATE_FILENAME);
25873
26126
  const content = this.toMarkdown(state);
25874
- await fs49.writeFile(filePath, content, "utf-8");
26127
+ await fs50.writeFile(filePath, content, "utf-8");
25875
26128
  }
25876
26129
  /**
25877
26130
  * Remove local state file
25878
26131
  */
25879
26132
  async remove(projectPath) {
25880
- const filePath = path52.join(projectPath, LOCAL_STATE_FILENAME);
26133
+ const filePath = path53.join(projectPath, LOCAL_STATE_FILENAME);
25881
26134
  try {
25882
- await fs49.unlink(filePath);
26135
+ await fs50.unlink(filePath);
25883
26136
  } catch (error) {
25884
26137
  if (!isNotFoundError(error)) throw error;
25885
26138
  }
@@ -25888,9 +26141,9 @@ var init_local_state_generator = __esm({
25888
26141
  * Check if local state file exists
25889
26142
  */
25890
26143
  async exists(projectPath) {
25891
- const filePath = path52.join(projectPath, LOCAL_STATE_FILENAME);
26144
+ const filePath = path53.join(projectPath, LOCAL_STATE_FILENAME);
25892
26145
  try {
25893
- await fs49.access(filePath);
26146
+ await fs50.access(filePath);
25894
26147
  return true;
25895
26148
  } catch {
25896
26149
  return false;
@@ -25969,11 +26222,11 @@ var init_local_state_generator = __esm({
25969
26222
  });
25970
26223
 
25971
26224
  // core/services/skill-lock.ts
25972
- import fs50 from "node:fs/promises";
26225
+ import fs51 from "node:fs/promises";
25973
26226
  import os14 from "node:os";
25974
- import path53 from "node:path";
26227
+ import path54 from "node:path";
25975
26228
  function getLockFilePath() {
25976
- return path53.join(os14.homedir(), ".prjct-cli", "skills", LOCK_FILE_NAME);
26229
+ return path54.join(os14.homedir(), ".prjct-cli", "skills", LOCK_FILE_NAME);
25977
26230
  }
25978
26231
  function createEmptyLockFile() {
25979
26232
  return {
@@ -25984,7 +26237,7 @@ function createEmptyLockFile() {
25984
26237
  }
25985
26238
  async function read() {
25986
26239
  try {
25987
- const content = await fs50.readFile(getLockFilePath(), "utf-8");
26240
+ const content = await fs51.readFile(getLockFilePath(), "utf-8");
25988
26241
  return JSON.parse(content);
25989
26242
  } catch {
25990
26243
  return createEmptyLockFile();
@@ -25992,9 +26245,9 @@ async function read() {
25992
26245
  }
25993
26246
  async function write(lockFile) {
25994
26247
  const lockPath = getLockFilePath();
25995
- await fs50.mkdir(path53.dirname(lockPath), { recursive: true });
26248
+ await fs51.mkdir(path54.dirname(lockPath), { recursive: true });
25996
26249
  lockFile.generatedAt = (/* @__PURE__ */ new Date()).toISOString();
25997
- await fs50.writeFile(lockPath, JSON.stringify(lockFile, null, 2), "utf-8");
26250
+ await fs51.writeFile(lockPath, JSON.stringify(lockFile, null, 2), "utf-8");
25998
26251
  }
25999
26252
  async function addEntry(entry) {
26000
26253
  const lockFile = await read();
@@ -26047,14 +26300,14 @@ var init_skill_lock = __esm({
26047
26300
 
26048
26301
  // core/services/skill-installer.ts
26049
26302
  import { exec as execCallback8 } from "node:child_process";
26050
- import fs51 from "node:fs/promises";
26303
+ import fs52 from "node:fs/promises";
26051
26304
  import os15 from "node:os";
26052
- import path54 from "node:path";
26305
+ import path55 from "node:path";
26053
26306
  import { promisify as promisify16 } from "node:util";
26054
26307
  import { glob } from "glob";
26055
26308
  function parseSource(source) {
26056
26309
  if (source.startsWith("./") || source.startsWith("/") || source.startsWith("~")) {
26057
- const resolvedPath = source.startsWith("~") ? path54.join(os15.homedir(), source.slice(1)) : path54.resolve(source);
26310
+ const resolvedPath = source.startsWith("~") ? path55.join(os15.homedir(), source.slice(1)) : path55.resolve(source);
26058
26311
  return {
26059
26312
  type: "local",
26060
26313
  localPath: resolvedPath,
@@ -26092,22 +26345,22 @@ function parseSource(source) {
26092
26345
  async function discoverSkills(dir) {
26093
26346
  const skills = [];
26094
26347
  try {
26095
- const rootSkill = path54.join(dir, "SKILL.md");
26096
- await fs51.access(rootSkill);
26097
- const dirName = path54.basename(dir);
26348
+ const rootSkill = path55.join(dir, "SKILL.md");
26349
+ await fs52.access(rootSkill);
26350
+ const dirName = path55.basename(dir);
26098
26351
  skills.push({ name: dirName, filePath: rootSkill });
26099
26352
  } catch {
26100
26353
  }
26101
26354
  const subdirSkills = await glob("*/SKILL.md", { cwd: dir, absolute: true });
26102
26355
  for (const filePath of subdirSkills) {
26103
- const name = path54.basename(path54.dirname(filePath));
26356
+ const name = path55.basename(path55.dirname(filePath));
26104
26357
  if (!skills.some((s) => s.name === name)) {
26105
26358
  skills.push({ name, filePath });
26106
26359
  }
26107
26360
  }
26108
26361
  const nestedSkills = await glob("skills/*/SKILL.md", { cwd: dir, absolute: true });
26109
26362
  for (const filePath of nestedSkills) {
26110
- const name = path54.basename(path54.dirname(filePath));
26363
+ const name = path55.basename(path55.dirname(filePath));
26111
26364
  if (!skills.some((s) => s.name === name)) {
26112
26365
  skills.push({ name, filePath });
26113
26366
  }
@@ -26143,16 +26396,16 @@ ${prjctBlock.join("\n")}
26143
26396
  ${content}`;
26144
26397
  }
26145
26398
  function getInstallDir() {
26146
- return path54.join(os15.homedir(), ".claude", "skills");
26399
+ return path55.join(os15.homedir(), ".claude", "skills");
26147
26400
  }
26148
26401
  async function installSkillFile(sourcePath, name, source, sha) {
26149
26402
  const installDir = getInstallDir();
26150
- const targetDir = path54.join(installDir, name);
26151
- const targetPath = path54.join(targetDir, "SKILL.md");
26152
- const content = await fs51.readFile(sourcePath, "utf-8");
26403
+ const targetDir = path55.join(installDir, name);
26404
+ const targetPath = path55.join(targetDir, "SKILL.md");
26405
+ const content = await fs52.readFile(sourcePath, "utf-8");
26153
26406
  const enrichedContent = injectSourceMetadata(content, source, sha);
26154
- await fs51.mkdir(targetDir, { recursive: true });
26155
- await fs51.writeFile(targetPath, enrichedContent, "utf-8");
26407
+ await fs52.mkdir(targetDir, { recursive: true });
26408
+ await fs52.writeFile(targetPath, enrichedContent, "utf-8");
26156
26409
  return {
26157
26410
  name,
26158
26411
  filePath: targetPath,
@@ -26169,7 +26422,7 @@ async function installFromGitHub(source) {
26169
26422
  );
26170
26423
  return result;
26171
26424
  }
26172
- const tmpDir = path54.join(os15.tmpdir(), `prjct-skill-${Date.now()}`);
26425
+ const tmpDir = path55.join(os15.tmpdir(), `prjct-skill-${Date.now()}`);
26173
26426
  try {
26174
26427
  const cloneUrl = `https://github.com/${source.owner}/${source.repo}.git`;
26175
26428
  await exec15(`git clone --depth 1 ${cloneUrl} ${tmpDir}`, { timeout: getTimeout("GIT_CLONE") });
@@ -26213,7 +26466,7 @@ async function installFromGitHub(source) {
26213
26466
  }
26214
26467
  } finally {
26215
26468
  try {
26216
- await fs51.rm(tmpDir, { recursive: true, force: true });
26469
+ await fs52.rm(tmpDir, { recursive: true, force: true });
26217
26470
  } catch {
26218
26471
  }
26219
26472
  }
@@ -26223,14 +26476,14 @@ async function installFromLocal(source) {
26223
26476
  const result = { installed: [], skipped: [], errors: [] };
26224
26477
  const localPath = source.localPath;
26225
26478
  try {
26226
- await fs51.access(localPath);
26479
+ await fs52.access(localPath);
26227
26480
  } catch {
26228
26481
  result.errors.push(`Local path not found: ${localPath}`);
26229
26482
  return result;
26230
26483
  }
26231
- const stat = await fs51.stat(localPath);
26484
+ const stat = await fs52.stat(localPath);
26232
26485
  if (stat.isFile()) {
26233
- const name = path54.basename(path54.dirname(localPath));
26486
+ const name = path55.basename(path55.dirname(localPath));
26234
26487
  try {
26235
26488
  const installed = await installSkillFile(localPath, name, source);
26236
26489
  const lockEntry = {
@@ -26270,14 +26523,14 @@ async function installFromLocal(source) {
26270
26523
  }
26271
26524
  async function remove(name) {
26272
26525
  const installDir = getInstallDir();
26273
- const subdirPath = path54.join(installDir, name);
26526
+ const subdirPath = path55.join(installDir, name);
26274
26527
  try {
26275
- await fs51.rm(subdirPath, { recursive: true, force: true });
26528
+ await fs52.rm(subdirPath, { recursive: true, force: true });
26276
26529
  } catch {
26277
26530
  }
26278
- const flatPath = path54.join(installDir, `${name}.md`);
26531
+ const flatPath = path55.join(installDir, `${name}.md`);
26279
26532
  try {
26280
- await fs51.rm(flatPath, { force: true });
26533
+ await fs52.rm(flatPath, { force: true });
26281
26534
  } catch {
26282
26535
  }
26283
26536
  return skillLock.removeEntry(name);
@@ -26325,8 +26578,8 @@ var init_skill_installer = __esm({
26325
26578
  });
26326
26579
 
26327
26580
  // core/services/stack-detector.ts
26328
- import fs52 from "node:fs/promises";
26329
- import path55 from "node:path";
26581
+ import fs53 from "node:fs/promises";
26582
+ import path56 from "node:path";
26330
26583
  var StackDetector;
26331
26584
  var init_stack_detector = __esm({
26332
26585
  "core/services/stack-detector.ts"() {
@@ -26485,8 +26738,8 @@ var init_stack_detector = __esm({
26485
26738
  */
26486
26739
  async readPackageJson() {
26487
26740
  try {
26488
- const pkgPath = path55.join(this.projectPath, "package.json");
26489
- const content = await fs52.readFile(pkgPath, "utf-8");
26741
+ const pkgPath = path56.join(this.projectPath, "package.json");
26742
+ const content = await fs53.readFile(pkgPath, "utf-8");
26490
26743
  return JSON.parse(content);
26491
26744
  } catch {
26492
26745
  return null;
@@ -26497,7 +26750,7 @@ var init_stack_detector = __esm({
26497
26750
  */
26498
26751
  async fileExists(filename) {
26499
26752
  try {
26500
- await fs52.access(path55.join(this.projectPath, filename));
26753
+ await fs53.access(path56.join(this.projectPath, filename));
26501
26754
  return true;
26502
26755
  } catch {
26503
26756
  return false;
@@ -26509,8 +26762,8 @@ var init_stack_detector = __esm({
26509
26762
 
26510
26763
  // core/services/sync-verifier.ts
26511
26764
  import { exec as exec16 } from "node:child_process";
26512
- import fs53 from "node:fs/promises";
26513
- import path56 from "node:path";
26765
+ import fs54 from "node:fs/promises";
26766
+ import path57 from "node:path";
26514
26767
  import { promisify as promisify17 } from "node:util";
26515
26768
  var execAsync10, BUILTIN_CHECKS, SyncVerifier, syncVerifier;
26516
26769
  var init_sync_verifier = __esm({
@@ -26527,9 +26780,9 @@ var init_sync_verifier = __esm({
26527
26780
  const expected = ["context/CLAUDE.md"];
26528
26781
  const missing = [];
26529
26782
  for (const file of expected) {
26530
- const filePath = path56.join(globalPath, file);
26783
+ const filePath = path57.join(globalPath, file);
26531
26784
  try {
26532
- await fs53.access(filePath);
26785
+ await fs54.access(filePath);
26533
26786
  } catch {
26534
26787
  missing.push(file);
26535
26788
  }
@@ -26550,9 +26803,9 @@ var init_sync_verifier = __esm({
26550
26803
  const jsonFiles = ["storage/state.json"];
26551
26804
  const invalid = [];
26552
26805
  for (const file of jsonFiles) {
26553
- const filePath = path56.join(globalPath, file);
26806
+ const filePath = path57.join(globalPath, file);
26554
26807
  try {
26555
- const content = await fs53.readFile(filePath, "utf-8");
26808
+ const content = await fs54.readFile(filePath, "utf-8");
26556
26809
  JSON.parse(content);
26557
26810
  } catch (error) {
26558
26811
  if (!isNotFoundError(error)) {
@@ -26573,7 +26826,7 @@ var init_sync_verifier = __esm({
26573
26826
  */
26574
26827
  async noSensitiveData(globalPath) {
26575
26828
  const start = Date.now();
26576
- const contextDir = path56.join(globalPath, "context");
26829
+ const contextDir = path57.join(globalPath, "context");
26577
26830
  const patterns = [
26578
26831
  /(?:api[_-]?key|apikey)\s*[:=]\s*['"][^'"]{10,}/i,
26579
26832
  /(?:password|passwd|pwd)\s*[:=]\s*['"][^'"]{4,}/i,
@@ -26581,10 +26834,10 @@ var init_sync_verifier = __esm({
26581
26834
  ];
26582
26835
  const violations = [];
26583
26836
  try {
26584
- const files = await fs53.readdir(contextDir);
26837
+ const files = await fs54.readdir(contextDir);
26585
26838
  for (const file of files) {
26586
26839
  if (!file.endsWith(".md")) continue;
26587
- const content = await fs53.readFile(path56.join(contextDir, file), "utf-8");
26840
+ const content = await fs54.readFile(path57.join(contextDir, file), "utf-8");
26588
26841
  for (const pattern of patterns) {
26589
26842
  if (pattern.test(content)) {
26590
26843
  violations.push(`${file}: potential sensitive data detected`);
@@ -26705,9 +26958,9 @@ var init_sync_verifier = __esm({
26705
26958
 
26706
26959
  // core/services/sync-service.ts
26707
26960
  import { exec as exec17 } from "node:child_process";
26708
- import fs54 from "node:fs/promises";
26961
+ import fs55 from "node:fs/promises";
26709
26962
  import os16 from "node:os";
26710
- import path57 from "node:path";
26963
+ import path58 from "node:path";
26711
26964
  import { promisify as promisify18 } from "node:util";
26712
26965
  var execAsync11, SyncService, syncService;
26713
26966
  var init_sync_service = __esm({
@@ -26715,6 +26968,8 @@ var init_sync_service = __esm({
26715
26968
  "use strict";
26716
26969
  init_ai_tools();
26717
26970
  init_bm25();
26971
+ init_change_propagator();
26972
+ init_file_hasher();
26718
26973
  init_git_cochange();
26719
26974
  init_import_graph();
26720
26975
  init_errors();
@@ -26794,20 +27049,80 @@ var init_sync_service = __esm({
26794
27049
  this.detectCommands(),
26795
27050
  this.detectStack()
26796
27051
  ]);
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
- });
27052
+ const isFullSync = options.full === true;
27053
+ let incrementalInfo;
27054
+ let shouldRebuildIndexes = true;
27055
+ let shouldRegenerateAgents = true;
27056
+ let changedDomains = /* @__PURE__ */ new Set();
27057
+ if (!isFullSync && hasHashRegistry(this.projectId)) {
27058
+ try {
27059
+ const { diff, currentHashes } = await detectChanges(this.projectPath, this.projectId);
27060
+ const totalChanged = diff.added.length + diff.modified.length + diff.deleted.length;
27061
+ if (totalChanged === 0 && !options.changedFiles?.length) {
27062
+ shouldRebuildIndexes = false;
27063
+ shouldRegenerateAgents = false;
27064
+ incrementalInfo = {
27065
+ isIncremental: true,
27066
+ filesChanged: 0,
27067
+ filesUnchanged: diff.unchanged.length,
27068
+ indexesRebuilt: false,
27069
+ agentsRegenerated: false,
27070
+ affectedDomains: []
27071
+ };
27072
+ } else {
27073
+ const propagated = propagateChanges(diff, this.projectId);
27074
+ changedDomains = affectedDomains(propagated.allAffected);
27075
+ const sourceExtensions = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
27076
+ const hasSourceChanges = propagated.allAffected.some((f) => {
27077
+ const ext = f.substring(f.lastIndexOf("."));
27078
+ return sourceExtensions.has(ext);
27079
+ });
27080
+ shouldRebuildIndexes = hasSourceChanges;
27081
+ const configChanged = propagated.directlyChanged.some(
27082
+ (f) => f === "package.json" || f === "tsconfig.json" || f.includes("Dockerfile") || f.includes("docker-compose")
27083
+ );
27084
+ shouldRegenerateAgents = configChanged;
27085
+ incrementalInfo = {
27086
+ isIncremental: true,
27087
+ filesChanged: totalChanged,
27088
+ filesUnchanged: diff.unchanged.length,
27089
+ indexesRebuilt: shouldRebuildIndexes,
27090
+ agentsRegenerated: shouldRegenerateAgents,
27091
+ affectedDomains: Array.from(changedDomains)
27092
+ };
27093
+ }
27094
+ saveHashes(this.projectId, currentHashes);
27095
+ } catch (error) {
27096
+ logger_default.debug("Incremental detection failed, falling back to full sync", {
27097
+ error: getErrorMessage(error)
27098
+ });
27099
+ }
27100
+ } else {
27101
+ try {
27102
+ const { currentHashes } = await detectChanges(this.projectPath, this.projectId);
27103
+ saveHashes(this.projectId, currentHashes);
27104
+ } catch (error) {
27105
+ logger_default.debug("Hash computation failed (non-critical)", {
27106
+ error: getErrorMessage(error)
27107
+ });
27108
+ }
26807
27109
  }
26808
- const agents = await this.generateAgents(stack, stats);
27110
+ if (shouldRebuildIndexes) {
27111
+ try {
27112
+ await Promise.all([
27113
+ indexProject(this.projectPath, this.projectId),
27114
+ indexImports(this.projectPath, this.projectId),
27115
+ indexCoChanges(this.projectPath, this.projectId)
27116
+ ]);
27117
+ } catch (error) {
27118
+ logger_default.debug("File ranking index build failed (non-critical)", {
27119
+ error: getErrorMessage(error)
27120
+ });
27121
+ }
27122
+ }
27123
+ const agents = shouldRegenerateAgents ? await this.generateAgents(stack, stats) : await this.loadExistingAgents();
26809
27124
  const skills = this.configureSkills(agents);
26810
- const skillsInstalled = await this.autoInstallSkills(agents);
27125
+ const skillsInstalled = shouldRegenerateAgents ? await this.autoInstallSkills(agents) : [];
26811
27126
  const sources = this.buildSources(stats, commands);
26812
27127
  const contextFiles = await this.generateContextFiles(git, stats, commands, agents, sources);
26813
27128
  const projectContext = {
@@ -26875,7 +27190,8 @@ var init_sync_service = __esm({
26875
27190
  success: r.success
26876
27191
  })),
26877
27192
  syncMetrics,
26878
- verification
27193
+ verification,
27194
+ incremental: incrementalInfo
26879
27195
  };
26880
27196
  } catch (error) {
26881
27197
  return {
@@ -26901,7 +27217,7 @@ var init_sync_service = __esm({
26901
27217
  async ensureDirectories() {
26902
27218
  const dirs = ["storage", "context", "agents", "memory", "analysis", "config", "sync"];
26903
27219
  await Promise.all(
26904
- dirs.map((dir) => fs54.mkdir(path57.join(this.globalPath, dir), { recursive: true }))
27220
+ dirs.map((dir) => fs55.mkdir(path58.join(this.globalPath, dir), { recursive: true }))
26905
27221
  );
26906
27222
  }
26907
27223
  // ==========================================================================
@@ -26972,7 +27288,7 @@ var init_sync_service = __esm({
26972
27288
  const stats = {
26973
27289
  fileCount: 0,
26974
27290
  version: "0.0.0",
26975
- name: path57.basename(this.projectPath),
27291
+ name: path58.basename(this.projectPath),
26976
27292
  ecosystem: "unknown",
26977
27293
  projectType: "simple",
26978
27294
  languages: [],
@@ -26989,8 +27305,8 @@ var init_sync_service = __esm({
26989
27305
  stats.fileCount = 0;
26990
27306
  }
26991
27307
  try {
26992
- const pkgPath = path57.join(this.projectPath, "package.json");
26993
- const pkg = JSON.parse(await fs54.readFile(pkgPath, "utf-8"));
27308
+ const pkgPath = path58.join(this.projectPath, "package.json");
27309
+ const pkg = JSON.parse(await fs55.readFile(pkgPath, "utf-8"));
26994
27310
  stats.version = pkg.version || "0.0.0";
26995
27311
  stats.name = pkg.name || stats.name;
26996
27312
  stats.ecosystem = "JavaScript";
@@ -27135,12 +27451,12 @@ var init_sync_service = __esm({
27135
27451
  // ==========================================================================
27136
27452
  async generateAgents(stack, stats) {
27137
27453
  const agents = [];
27138
- const agentsPath = path57.join(this.globalPath, "agents");
27454
+ const agentsPath = path58.join(this.globalPath, "agents");
27139
27455
  try {
27140
- const files = await fs54.readdir(agentsPath);
27456
+ const files = await fs55.readdir(agentsPath);
27141
27457
  for (const file of files) {
27142
27458
  if (file.endsWith(".md")) {
27143
- await fs54.unlink(path57.join(agentsPath, file));
27459
+ await fs55.unlink(path58.join(agentsPath, file));
27144
27460
  }
27145
27461
  }
27146
27462
  } catch (error) {
@@ -27178,6 +27494,27 @@ var init_sync_service = __esm({
27178
27494
  }
27179
27495
  return agents;
27180
27496
  }
27497
+ /**
27498
+ * Load existing agent info from disk (for incremental sync when agents don't need regeneration).
27499
+ * Reads the agents directory and returns metadata without regenerating files.
27500
+ */
27501
+ async loadExistingAgents() {
27502
+ const agentsPath = path58.join(this.globalPath, "agents");
27503
+ const agents = [];
27504
+ try {
27505
+ const files = await fs55.readdir(agentsPath);
27506
+ const workflowNames = /* @__PURE__ */ new Set(["prjct-workflow", "prjct-planner", "prjct-shipper"]);
27507
+ for (const file of files) {
27508
+ if (!file.endsWith(".md")) continue;
27509
+ const name = file.replace(".md", "");
27510
+ const type = workflowNames.has(name) ? "workflow" : "domain";
27511
+ agents.push({ name, type });
27512
+ }
27513
+ } catch {
27514
+ return [];
27515
+ }
27516
+ return agents;
27517
+ }
27181
27518
  /**
27182
27519
  * Resolve {{> partial-name }} includes in template content.
27183
27520
  * Loads partials from templates/subagents/.
@@ -27189,7 +27526,7 @@ var init_sync_service = __esm({
27189
27526
  let resolved = content;
27190
27527
  for (const match of matches) {
27191
27528
  const partialName = match[1];
27192
- const partialPath = path57.join(
27529
+ const partialPath = path58.join(
27193
27530
  __dirname,
27194
27531
  "..",
27195
27532
  "..",
@@ -27198,7 +27535,7 @@ var init_sync_service = __esm({
27198
27535
  `${partialName}.md`
27199
27536
  );
27200
27537
  try {
27201
- const partialContent = await fs54.readFile(partialPath, "utf-8");
27538
+ const partialContent = await fs55.readFile(partialPath, "utf-8");
27202
27539
  resolved = resolved.replace(match[0], partialContent.trim());
27203
27540
  } catch {
27204
27541
  resolved = resolved.replace(match[0], `<!-- partial "${partialName}" not found -->`);
@@ -27209,7 +27546,7 @@ var init_sync_service = __esm({
27209
27546
  async generateWorkflowAgent(name, agentsPath) {
27210
27547
  let content = "";
27211
27548
  try {
27212
- const templatePath = path57.join(
27549
+ const templatePath = path58.join(
27213
27550
  __dirname,
27214
27551
  "..",
27215
27552
  "..",
@@ -27218,7 +27555,7 @@ var init_sync_service = __esm({
27218
27555
  "workflow",
27219
27556
  `${name}.md`
27220
27557
  );
27221
- content = await fs54.readFile(templatePath, "utf-8");
27558
+ content = await fs55.readFile(templatePath, "utf-8");
27222
27559
  content = await this.resolveTemplateIncludes(content);
27223
27560
  } catch (error) {
27224
27561
  logger_default.debug("Workflow agent template not found, generating minimal", {
@@ -27227,12 +27564,12 @@ var init_sync_service = __esm({
27227
27564
  });
27228
27565
  content = this.generateMinimalWorkflowAgent(name);
27229
27566
  }
27230
- await fs54.writeFile(path57.join(agentsPath, `${name}.md`), content, "utf-8");
27567
+ await fs55.writeFile(path58.join(agentsPath, `${name}.md`), content, "utf-8");
27231
27568
  }
27232
27569
  async generateDomainAgent(name, agentsPath, stats, stack) {
27233
27570
  let content = "";
27234
27571
  try {
27235
- const templatePath = path57.join(
27572
+ const templatePath = path58.join(
27236
27573
  __dirname,
27237
27574
  "..",
27238
27575
  "..",
@@ -27241,7 +27578,7 @@ var init_sync_service = __esm({
27241
27578
  "domain",
27242
27579
  `${name}.md`
27243
27580
  );
27244
- content = await fs54.readFile(templatePath, "utf-8");
27581
+ content = await fs55.readFile(templatePath, "utf-8");
27245
27582
  content = await this.resolveTemplateIncludes(content);
27246
27583
  content = content.replace("{projectName}", stats.name);
27247
27584
  content = content.replace("{frameworks}", stack.frameworks.join(", ") || "None detected");
@@ -27253,7 +27590,7 @@ var init_sync_service = __esm({
27253
27590
  });
27254
27591
  content = this.generateMinimalDomainAgent(name, stats, stack);
27255
27592
  }
27256
- await fs54.writeFile(path57.join(agentsPath, `${name}.md`), content, "utf-8");
27593
+ await fs55.writeFile(path58.join(agentsPath, `${name}.md`), content, "utf-8");
27257
27594
  }
27258
27595
  generateMinimalWorkflowAgent(name) {
27259
27596
  const descriptions = {
@@ -27321,8 +27658,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
27321
27658
  })),
27322
27659
  agentSkillMap: Object.fromEntries(skills.map((s) => [s.agent, s.skill]))
27323
27660
  };
27324
- fs54.writeFile(
27325
- path57.join(this.globalPath, "config", "skills.json"),
27661
+ fs55.writeFile(
27662
+ path58.join(this.globalPath, "config", "skills.json"),
27326
27663
  JSON.stringify(skillsConfig, null, 2),
27327
27664
  "utf-8"
27328
27665
  ).catch((error) => {
@@ -27340,7 +27677,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
27340
27677
  async autoInstallSkills(agents) {
27341
27678
  const results = [];
27342
27679
  try {
27343
- const mappingsPath = path57.join(
27680
+ const mappingsPath = path58.join(
27344
27681
  __dirname,
27345
27682
  "..",
27346
27683
  "..",
@@ -27348,7 +27685,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
27348
27685
  "config",
27349
27686
  "skill-mappings.json"
27350
27687
  );
27351
- const mappingsContent = await fs54.readFile(mappingsPath, "utf-8");
27688
+ const mappingsContent = await fs55.readFile(mappingsPath, "utf-8");
27352
27689
  const mappings = JSON.parse(mappingsContent);
27353
27690
  const agentToSkillMap = mappings.agentToSkillMap || {};
27354
27691
  const packagesToInstall = [];
@@ -27361,18 +27698,18 @@ You are the ${name} expert for this project. Apply best practices for the detect
27361
27698
  }
27362
27699
  }
27363
27700
  if (packagesToInstall.length === 0) return results;
27364
- const skillsDir = path57.join(os16.homedir(), ".claude", "skills");
27701
+ const skillsDir = path58.join(os16.homedir(), ".claude", "skills");
27365
27702
  for (const { pkg, agent } of packagesToInstall) {
27366
27703
  const skillName = pkg.split("/").pop() || pkg;
27367
- const subdirPath = path57.join(skillsDir, skillName, "SKILL.md");
27368
- const flatPath = path57.join(skillsDir, `${skillName}.md`);
27704
+ const subdirPath = path58.join(skillsDir, skillName, "SKILL.md");
27705
+ const flatPath = path58.join(skillsDir, `${skillName}.md`);
27369
27706
  let alreadyInstalled = false;
27370
27707
  try {
27371
- await fs54.access(subdirPath);
27708
+ await fs55.access(subdirPath);
27372
27709
  alreadyInstalled = true;
27373
27710
  } catch {
27374
27711
  try {
27375
- await fs54.access(flatPath);
27712
+ await fs55.access(flatPath);
27376
27713
  alreadyInstalled = true;
27377
27714
  } catch {
27378
27715
  }
@@ -27424,10 +27761,10 @@ You are the ${name} expert for this project. Apply best practices for the detect
27424
27761
  // PROJECT.JSON UPDATE
27425
27762
  // ==========================================================================
27426
27763
  async updateProjectJson(git, stats) {
27427
- const projectJsonPath = path57.join(this.globalPath, "project.json");
27764
+ const projectJsonPath = path58.join(this.globalPath, "project.json");
27428
27765
  let existing = {};
27429
27766
  try {
27430
- existing = JSON.parse(await fs54.readFile(projectJsonPath, "utf-8"));
27767
+ existing = JSON.parse(await fs55.readFile(projectJsonPath, "utf-8"));
27431
27768
  } catch (error) {
27432
27769
  logger_default.debug("No existing project.json", {
27433
27770
  path: projectJsonPath,
@@ -27453,16 +27790,16 @@ You are the ${name} expert for this project. Apply best practices for the detect
27453
27790
  lastSyncCommit: git.recentCommits[0]?.hash || null,
27454
27791
  lastSyncBranch: git.branch
27455
27792
  };
27456
- await fs54.writeFile(projectJsonPath, JSON.stringify(updated, null, 2), "utf-8");
27793
+ await fs55.writeFile(projectJsonPath, JSON.stringify(updated, null, 2), "utf-8");
27457
27794
  }
27458
27795
  // ==========================================================================
27459
27796
  // STATE.JSON UPDATE
27460
27797
  // ==========================================================================
27461
27798
  async updateStateJson(stats, stack) {
27462
- const statePath = path57.join(this.globalPath, "storage", "state.json");
27799
+ const statePath = path58.join(this.globalPath, "storage", "state.json");
27463
27800
  let state = {};
27464
27801
  try {
27465
- state = JSON.parse(await fs54.readFile(statePath, "utf-8"));
27802
+ state = JSON.parse(await fs55.readFile(statePath, "utf-8"));
27466
27803
  } catch (error) {
27467
27804
  logger_default.debug("No existing state.json", { path: statePath, error: getErrorMessage(error) });
27468
27805
  }
@@ -27490,7 +27827,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
27490
27827
  lastAction: "Synced project",
27491
27828
  nextAction: 'Run `p. task "description"` to start working'
27492
27829
  };
27493
- await fs54.writeFile(statePath, JSON.stringify(state, null, 2), "utf-8");
27830
+ await fs55.writeFile(statePath, JSON.stringify(state, null, 2), "utf-8");
27494
27831
  try {
27495
27832
  await localStateGenerator.generate(
27496
27833
  this.projectPath,
@@ -27504,7 +27841,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
27504
27841
  // MEMORY LOGGING
27505
27842
  // ==========================================================================
27506
27843
  async logToMemory(git, stats) {
27507
- const memoryPath = path57.join(this.globalPath, "memory", "events.jsonl");
27844
+ const memoryPath = path58.join(this.globalPath, "memory", "events.jsonl");
27508
27845
  const event = {
27509
27846
  ts: getTimestamp(),
27510
27847
  action: "sync",
@@ -27513,7 +27850,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
27513
27850
  fileCount: stats.fileCount,
27514
27851
  commitCount: git.commits
27515
27852
  };
27516
- await fs54.appendFile(memoryPath, `${JSON.stringify(event)}
27853
+ await fs55.appendFile(memoryPath, `${JSON.stringify(event)}
27517
27854
  `, "utf-8");
27518
27855
  }
27519
27856
  // ==========================================================================
@@ -27533,8 +27870,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
27533
27870
  let filteredChars = 0;
27534
27871
  for (const file of contextFiles) {
27535
27872
  try {
27536
- const filePath = path57.join(this.globalPath, file);
27537
- const content = await fs54.readFile(filePath, "utf-8");
27873
+ const filePath = path58.join(this.globalPath, file);
27874
+ const content = await fs55.readFile(filePath, "utf-8");
27538
27875
  filteredChars += content.length;
27539
27876
  } catch (error) {
27540
27877
  logger_default.debug("Context file not found for metrics", { file, error: getErrorMessage(error) });
@@ -27542,8 +27879,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
27542
27879
  }
27543
27880
  for (const agent of agents) {
27544
27881
  try {
27545
- const agentPath = path57.join(this.globalPath, "agents", `${agent.name}.md`);
27546
- const content = await fs54.readFile(agentPath, "utf-8");
27882
+ const agentPath = path58.join(this.globalPath, "agents", `${agent.name}.md`);
27883
+ const content = await fs55.readFile(agentPath, "utf-8");
27547
27884
  filteredChars += content.length;
27548
27885
  } catch (error) {
27549
27886
  logger_default.debug("Agent file not found for metrics", {
@@ -27605,7 +27942,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
27605
27942
  // ==========================================================================
27606
27943
  async fileExists(filename) {
27607
27944
  try {
27608
- await fs54.access(path57.join(this.projectPath, filename));
27945
+ await fs55.access(path58.join(this.projectPath, filename));
27609
27946
  return true;
27610
27947
  } catch (error) {
27611
27948
  logger_default.debug("File not found", { filename, error: getErrorMessage(error) });
@@ -27614,8 +27951,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
27614
27951
  }
27615
27952
  async getCliVersion() {
27616
27953
  try {
27617
- const pkgPath = path57.join(__dirname, "..", "..", "package.json");
27618
- const pkg = JSON.parse(await fs54.readFile(pkgPath, "utf-8"));
27954
+ const pkgPath = path58.join(__dirname, "..", "..", "package.json");
27955
+ const pkg = JSON.parse(await fs55.readFile(pkgPath, "utf-8"));
27619
27956
  return pkg.version || "0.0.0";
27620
27957
  } catch (error) {
27621
27958
  logger_default.debug("Failed to read CLI version", { error: getErrorMessage(error) });
@@ -27776,22 +28113,22 @@ __export(uninstall_exports, {
27776
28113
  uninstall: () => uninstall
27777
28114
  });
27778
28115
  import { execSync as execSync3 } from "node:child_process";
27779
- import fs55 from "node:fs/promises";
28116
+ import fs56 from "node:fs/promises";
27780
28117
  import os17 from "node:os";
27781
- import path58 from "node:path";
28118
+ import path59 from "node:path";
27782
28119
  import readline2 from "node:readline";
27783
28120
  import chalk12 from "chalk";
27784
28121
  async function getDirectorySize(dirPath) {
27785
28122
  let totalSize = 0;
27786
28123
  try {
27787
- const entries = await fs55.readdir(dirPath, { withFileTypes: true });
28124
+ const entries = await fs56.readdir(dirPath, { withFileTypes: true });
27788
28125
  for (const entry of entries) {
27789
- const entryPath = path58.join(dirPath, entry.name);
28126
+ const entryPath = path59.join(dirPath, entry.name);
27790
28127
  if (entry.isDirectory()) {
27791
28128
  totalSize += await getDirectorySize(entryPath);
27792
28129
  } else {
27793
28130
  try {
27794
- const stats = await fs55.stat(entryPath);
28131
+ const stats = await fs56.stat(entryPath);
27795
28132
  totalSize += stats.size;
27796
28133
  } catch {
27797
28134
  }
@@ -27810,7 +28147,7 @@ function formatSize(bytes) {
27810
28147
  }
27811
28148
  async function countDirectoryItems(dirPath) {
27812
28149
  try {
27813
- const entries = await fs55.readdir(dirPath, { withFileTypes: true });
28150
+ const entries = await fs56.readdir(dirPath, { withFileTypes: true });
27814
28151
  return entries.filter((e) => e.isDirectory()).length;
27815
28152
  } catch {
27816
28153
  return 0;
@@ -27843,7 +28180,7 @@ async function gatherUninstallItems() {
27843
28180
  const providerPaths = getProviderPaths();
27844
28181
  const prjctCliPath = path_manager_default.getGlobalBasePath();
27845
28182
  const prjctCliExists = await fileExists(prjctCliPath);
27846
- const projectCount = prjctCliExists ? await countDirectoryItems(path58.join(prjctCliPath, "projects")) : 0;
28183
+ const projectCount = prjctCliExists ? await countDirectoryItems(path59.join(prjctCliPath, "projects")) : 0;
27847
28184
  const prjctCliSize = prjctCliExists ? await getDirectorySize(prjctCliPath) : 0;
27848
28185
  items.push({
27849
28186
  path: prjctCliPath,
@@ -27853,12 +28190,12 @@ async function gatherUninstallItems() {
27853
28190
  count: projectCount,
27854
28191
  exists: prjctCliExists
27855
28192
  });
27856
- const claudeMdPath = path58.join(providerPaths.claude.config, "CLAUDE.md");
28193
+ const claudeMdPath = path59.join(providerPaths.claude.config, "CLAUDE.md");
27857
28194
  const claudeMdExists = await fileExists(claudeMdPath);
27858
28195
  let hasPrjctSection = false;
27859
28196
  if (claudeMdExists) {
27860
28197
  try {
27861
- const content = await fs55.readFile(claudeMdPath, "utf-8");
28198
+ const content = await fs56.readFile(claudeMdPath, "utf-8");
27862
28199
  hasPrjctSection = content.includes(PRJCT_START_MARKER) && content.includes(PRJCT_END_MARKER);
27863
28200
  } catch {
27864
28201
  }
@@ -27887,7 +28224,7 @@ async function gatherUninstallItems() {
27887
28224
  description: "Claude router",
27888
28225
  exists: claudeRouterExists
27889
28226
  });
27890
- const statusLinePath = path58.join(providerPaths.claude.config, "prjct-statusline.sh");
28227
+ const statusLinePath = path59.join(providerPaths.claude.config, "prjct-statusline.sh");
27891
28228
  const statusLineExists = await fileExists(statusLinePath);
27892
28229
  items.push({
27893
28230
  path: statusLinePath,
@@ -27903,12 +28240,12 @@ async function gatherUninstallItems() {
27903
28240
  description: "Gemini router",
27904
28241
  exists: geminiRouterExists
27905
28242
  });
27906
- const geminiMdPath = path58.join(providerPaths.gemini.config, "GEMINI.md");
28243
+ const geminiMdPath = path59.join(providerPaths.gemini.config, "GEMINI.md");
27907
28244
  const geminiMdExists = await fileExists(geminiMdPath);
27908
28245
  let hasGeminiPrjctSection = false;
27909
28246
  if (geminiMdExists) {
27910
28247
  try {
27911
- const content = await fs55.readFile(geminiMdPath, "utf-8");
28248
+ const content = await fs56.readFile(geminiMdPath, "utf-8");
27912
28249
  hasGeminiPrjctSection = content.includes(PRJCT_START_MARKER) && content.includes(PRJCT_END_MARKER);
27913
28250
  } catch {
27914
28251
  }
@@ -27925,7 +28262,7 @@ async function gatherUninstallItems() {
27925
28262
  }
27926
28263
  async function removePrjctSection(filePath) {
27927
28264
  try {
27928
- const content = await fs55.readFile(filePath, "utf-8");
28265
+ const content = await fs56.readFile(filePath, "utf-8");
27929
28266
  if (!content.includes(PRJCT_START_MARKER) || !content.includes(PRJCT_END_MARKER)) {
27930
28267
  return false;
27931
28268
  }
@@ -27934,9 +28271,9 @@ async function removePrjctSection(filePath) {
27934
28271
  let newContent = content.substring(0, startIndex) + content.substring(endIndex);
27935
28272
  newContent = newContent.replace(/\n{3,}/g, "\n\n").trim();
27936
28273
  if (!newContent || newContent.trim().length === 0) {
27937
- await fs55.unlink(filePath);
28274
+ await fs56.unlink(filePath);
27938
28275
  } else {
27939
- await fs55.writeFile(filePath, `${newContent}
28276
+ await fs56.writeFile(filePath, `${newContent}
27940
28277
  `, "utf-8");
27941
28278
  }
27942
28279
  return true;
@@ -27947,12 +28284,12 @@ async function removePrjctSection(filePath) {
27947
28284
  async function createBackup3() {
27948
28285
  const homeDir = os17.homedir();
27949
28286
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
27950
- const backupDir = path58.join(homeDir, `.prjct-backup-${timestamp}`);
28287
+ const backupDir = path59.join(homeDir, `.prjct-backup-${timestamp}`);
27951
28288
  try {
27952
- await fs55.mkdir(backupDir, { recursive: true });
28289
+ await fs56.mkdir(backupDir, { recursive: true });
27953
28290
  const prjctCliPath = path_manager_default.getGlobalBasePath();
27954
28291
  if (await fileExists(prjctCliPath)) {
27955
- await copyDirectory(prjctCliPath, path58.join(backupDir, ".prjct-cli"));
28292
+ await copyDirectory(prjctCliPath, path59.join(backupDir, ".prjct-cli"));
27956
28293
  }
27957
28294
  return backupDir;
27958
28295
  } catch {
@@ -27960,15 +28297,15 @@ async function createBackup3() {
27960
28297
  }
27961
28298
  }
27962
28299
  async function copyDirectory(src, dest) {
27963
- await fs55.mkdir(dest, { recursive: true });
27964
- const entries = await fs55.readdir(src, { withFileTypes: true });
28300
+ await fs56.mkdir(dest, { recursive: true });
28301
+ const entries = await fs56.readdir(src, { withFileTypes: true });
27965
28302
  for (const entry of entries) {
27966
- const srcPath = path58.join(src, entry.name);
27967
- const destPath = path58.join(dest, entry.name);
28303
+ const srcPath = path59.join(src, entry.name);
28304
+ const destPath = path59.join(dest, entry.name);
27968
28305
  if (entry.isDirectory()) {
27969
28306
  await copyDirectory(srcPath, destPath);
27970
28307
  } else {
27971
- await fs55.copyFile(srcPath, destPath);
28308
+ await fs56.copyFile(srcPath, destPath);
27972
28309
  }
27973
28310
  }
27974
28311
  }
@@ -27984,10 +28321,10 @@ async function performUninstall(items, installation, options) {
27984
28321
  deleted.push(item.path);
27985
28322
  }
27986
28323
  } else if (item.type === "directory") {
27987
- await fs55.rm(item.path, { recursive: true, force: true });
28324
+ await fs56.rm(item.path, { recursive: true, force: true });
27988
28325
  deleted.push(item.path);
27989
28326
  } else if (item.type === "file") {
27990
- await fs55.unlink(item.path);
28327
+ await fs56.unlink(item.path);
27991
28328
  deleted.push(item.path);
27992
28329
  }
27993
28330
  } catch (error) {
@@ -28164,7 +28501,7 @@ __export(watch_service_exports, {
28164
28501
  WatchService: () => WatchService,
28165
28502
  watchService: () => watchService
28166
28503
  });
28167
- import path59 from "node:path";
28504
+ import path60 from "node:path";
28168
28505
  import chalk13 from "chalk";
28169
28506
  import chokidar from "chokidar";
28170
28507
  var TRIGGER_PATTERNS, IGNORE_PATTERNS2, WatchService, watchService;
@@ -28353,7 +28690,7 @@ ${chalk13.dim(`[${timestamp}]`)} ${chalk13.cyan("\u27F3")} ${filesSummary} chang
28353
28690
  );
28354
28691
  }
28355
28692
  try {
28356
- const result = await syncService.sync(this.projectPath);
28693
+ const result = await syncService.sync(this.projectPath, { changedFiles });
28357
28694
  this.lastSyncTime = Date.now();
28358
28695
  this.syncCount++;
28359
28696
  if (result.success) {
@@ -28385,7 +28722,7 @@ ${chalk13.dim(`[${timestamp}]`)} ${chalk13.cyan("\u27F3")} ${filesSummary} chang
28385
28722
  printStartup() {
28386
28723
  console.log("");
28387
28724
  console.log(chalk13.cyan("\u{1F441}\uFE0F Watching for changes..."));
28388
- console.log(chalk13.dim(` Project: ${path59.basename(this.projectPath)}`));
28725
+ console.log(chalk13.dim(` Project: ${path60.basename(this.projectPath)}`));
28389
28726
  console.log(chalk13.dim(` Debounce: ${this.options.debounceMs}ms`));
28390
28727
  console.log(chalk13.dim(` Min interval: ${this.options.minIntervalMs / 1e3}s`));
28391
28728
  console.log("");
@@ -28558,11 +28895,13 @@ var init_command_data = __esm({
28558
28895
  name: "sync",
28559
28896
  group: "core",
28560
28897
  description: "Sync project state and update workflow agents",
28561
- usage: { claude: "/p:sync", terminal: "prjct sync [--package=<name>]" },
28898
+ usage: { claude: "/p:sync", terminal: "prjct sync [--package=<name>] [--full]" },
28562
28899
  implemented: true,
28563
28900
  hasTemplate: true,
28564
28901
  requiresProject: true,
28565
28902
  features: [
28903
+ "Incremental sync: only re-analyzes changed files (default)",
28904
+ "Force full sync: --full bypasses incremental cache",
28566
28905
  "Monorepo support: --package=<name> for single package sync",
28567
28906
  "Nested PRJCT.md inheritance",
28568
28907
  "Per-package CLAUDE.md generation"
@@ -29116,9 +29455,9 @@ __export(setup_exports, {
29116
29455
  run: () => run
29117
29456
  });
29118
29457
  import { execSync as execSync4 } from "node:child_process";
29119
- import fs56 from "node:fs/promises";
29458
+ import fs57 from "node:fs/promises";
29120
29459
  import os18 from "node:os";
29121
- import path60 from "node:path";
29460
+ import path61 from "node:path";
29122
29461
  import chalk15 from "chalk";
29123
29462
  async function installAICLI(provider) {
29124
29463
  const packageName = provider.name === "claude" ? "@anthropic-ai/claude-code" : "@google/gemini-cli";
@@ -29257,12 +29596,12 @@ async function run() {
29257
29596
  }
29258
29597
  async function installGeminiRouter() {
29259
29598
  try {
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 });
29599
+ const geminiCommandsDir = path61.join(os18.homedir(), ".gemini", "commands");
29600
+ const routerSource = path61.join(PACKAGE_ROOT, "templates", "commands", "p.toml");
29601
+ const routerDest = path61.join(geminiCommandsDir, "p.toml");
29602
+ await fs57.mkdir(geminiCommandsDir, { recursive: true });
29264
29603
  if (await fileExists(routerSource)) {
29265
- await fs56.copyFile(routerSource, routerDest);
29604
+ await fs57.copyFile(routerSource, routerDest);
29266
29605
  return true;
29267
29606
  }
29268
29607
  return false;
@@ -29273,15 +29612,15 @@ async function installGeminiRouter() {
29273
29612
  }
29274
29613
  async function installGeminiGlobalConfig() {
29275
29614
  try {
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");
29615
+ const geminiDir = path61.join(os18.homedir(), ".gemini");
29616
+ const globalConfigPath = path61.join(geminiDir, "GEMINI.md");
29617
+ const templatePath = path61.join(PACKAGE_ROOT, "templates", "global", "GEMINI.md");
29618
+ await fs57.mkdir(geminiDir, { recursive: true });
29619
+ const templateContent = await fs57.readFile(templatePath, "utf-8");
29281
29620
  let existingContent = "";
29282
29621
  let configExists = false;
29283
29622
  try {
29284
- existingContent = await fs56.readFile(globalConfigPath, "utf-8");
29623
+ existingContent = await fs57.readFile(globalConfigPath, "utf-8");
29285
29624
  configExists = true;
29286
29625
  } catch (error) {
29287
29626
  if (isNotFoundError(error)) {
@@ -29291,7 +29630,7 @@ async function installGeminiGlobalConfig() {
29291
29630
  }
29292
29631
  }
29293
29632
  if (!configExists) {
29294
- await fs56.writeFile(globalConfigPath, templateContent, "utf-8");
29633
+ await fs57.writeFile(globalConfigPath, templateContent, "utf-8");
29295
29634
  return { success: true, action: "created" };
29296
29635
  }
29297
29636
  const startMarker = "<!-- prjct:start - DO NOT REMOVE THIS MARKER -->";
@@ -29301,7 +29640,7 @@ async function installGeminiGlobalConfig() {
29301
29640
  const updatedContent2 = `${existingContent}
29302
29641
 
29303
29642
  ${templateContent}`;
29304
- await fs56.writeFile(globalConfigPath, updatedContent2, "utf-8");
29643
+ await fs57.writeFile(globalConfigPath, updatedContent2, "utf-8");
29305
29644
  return { success: true, action: "appended" };
29306
29645
  }
29307
29646
  const beforeMarker = existingContent.substring(0, existingContent.indexOf(startMarker));
@@ -29313,7 +29652,7 @@ ${templateContent}`;
29313
29652
  templateContent.indexOf(endMarker) + endMarker.length
29314
29653
  );
29315
29654
  const updatedContent = beforeMarker + prjctSection + afterMarker;
29316
- await fs56.writeFile(globalConfigPath, updatedContent, "utf-8");
29655
+ await fs57.writeFile(globalConfigPath, updatedContent, "utf-8");
29317
29656
  return { success: true, action: "updated" };
29318
29657
  } catch (error) {
29319
29658
  logger_default.warn(`Gemini config warning: ${getErrorMessage2(error)}`);
@@ -29322,18 +29661,18 @@ ${templateContent}`;
29322
29661
  }
29323
29662
  async function installAntigravitySkill() {
29324
29663
  try {
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 });
29664
+ const antigravitySkillsDir = path61.join(os18.homedir(), ".gemini", "antigravity", "skills");
29665
+ const prjctSkillDir = path61.join(antigravitySkillsDir, "prjct");
29666
+ const skillMdPath = path61.join(prjctSkillDir, "SKILL.md");
29667
+ const templatePath = path61.join(PACKAGE_ROOT, "templates", "antigravity", "SKILL.md");
29668
+ await fs57.mkdir(prjctSkillDir, { recursive: true });
29330
29669
  const skillExists = await fileExists(skillMdPath);
29331
29670
  if (!await fileExists(templatePath)) {
29332
29671
  logger_default.warn("Antigravity SKILL.md template not found");
29333
29672
  return { success: false, action: null };
29334
29673
  }
29335
- const templateContent = await fs56.readFile(templatePath, "utf-8");
29336
- await fs56.writeFile(skillMdPath, templateContent, "utf-8");
29674
+ const templateContent = await fs57.readFile(templatePath, "utf-8");
29675
+ await fs57.writeFile(skillMdPath, templateContent, "utf-8");
29337
29676
  return { success: true, action: skillExists ? "updated" : "created" };
29338
29677
  } catch (error) {
29339
29678
  logger_default.warn(`Antigravity skill warning: ${getErrorMessage2(error)}`);
@@ -29352,24 +29691,24 @@ async function installCursorProject(projectRoot) {
29352
29691
  gitignoreUpdated: false
29353
29692
  };
29354
29693
  try {
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 });
29694
+ const cursorDir = path61.join(projectRoot, ".cursor");
29695
+ const rulesDir = path61.join(cursorDir, "rules");
29696
+ const commandsDir = path61.join(cursorDir, "commands");
29697
+ const routerMdcDest = path61.join(rulesDir, "prjct.mdc");
29698
+ const routerMdcSource = path61.join(PACKAGE_ROOT, "templates", "cursor", "router.mdc");
29699
+ const cursorCommandsSource = path61.join(PACKAGE_ROOT, "templates", "cursor", "commands");
29700
+ await fs57.mkdir(rulesDir, { recursive: true });
29701
+ await fs57.mkdir(commandsDir, { recursive: true });
29363
29702
  if (await fileExists(routerMdcSource)) {
29364
- await fs56.copyFile(routerMdcSource, routerMdcDest);
29703
+ await fs57.copyFile(routerMdcSource, routerMdcDest);
29365
29704
  result.rulesCreated = true;
29366
29705
  }
29367
29706
  if (await fileExists(cursorCommandsSource)) {
29368
- const commandFiles = (await fs56.readdir(cursorCommandsSource)).filter((f) => f.endsWith(".md"));
29707
+ const commandFiles = (await fs57.readdir(cursorCommandsSource)).filter((f) => f.endsWith(".md"));
29369
29708
  for (const file of commandFiles) {
29370
- const src = path60.join(cursorCommandsSource, file);
29371
- const dest = path60.join(commandsDir, file);
29372
- await fs56.copyFile(src, dest);
29709
+ const src = path61.join(cursorCommandsSource, file);
29710
+ const dest = path61.join(commandsDir, file);
29711
+ await fs57.copyFile(src, dest);
29373
29712
  }
29374
29713
  result.commandsCreated = commandFiles.length > 0;
29375
29714
  }
@@ -29383,7 +29722,7 @@ async function installCursorProject(projectRoot) {
29383
29722
  }
29384
29723
  async function addCursorToGitignore(projectRoot) {
29385
29724
  try {
29386
- const gitignorePath = path60.join(projectRoot, ".gitignore");
29725
+ const gitignorePath = path61.join(projectRoot, ".gitignore");
29387
29726
  const entriesToAdd = [
29388
29727
  "# prjct Cursor routers (regenerated per-developer)",
29389
29728
  ".cursor/rules/prjct.mdc",
@@ -29398,7 +29737,7 @@ async function addCursorToGitignore(projectRoot) {
29398
29737
  let content = "";
29399
29738
  let configExists = false;
29400
29739
  try {
29401
- content = await fs56.readFile(gitignorePath, "utf-8");
29740
+ content = await fs57.readFile(gitignorePath, "utf-8");
29402
29741
  configExists = true;
29403
29742
  } catch (error) {
29404
29743
  if (!isNotFoundError(error)) {
@@ -29413,7 +29752,7 @@ async function addCursorToGitignore(projectRoot) {
29413
29752
  ${entriesToAdd.join("\n")}
29414
29753
  ` : `${entriesToAdd.join("\n")}
29415
29754
  `;
29416
- await fs56.writeFile(gitignorePath, newContent, "utf-8");
29755
+ await fs57.writeFile(gitignorePath, newContent, "utf-8");
29417
29756
  return true;
29418
29757
  } catch (error) {
29419
29758
  logger_default.warn(`Gitignore update warning: ${getErrorMessage2(error)}`);
@@ -29421,11 +29760,11 @@ ${entriesToAdd.join("\n")}
29421
29760
  }
29422
29761
  }
29423
29762
  async function hasCursorProject(projectRoot) {
29424
- return await fileExists(path60.join(projectRoot, ".cursor"));
29763
+ return await fileExists(path61.join(projectRoot, ".cursor"));
29425
29764
  }
29426
29765
  async function needsCursorRegeneration(projectRoot) {
29427
- const cursorDir = path60.join(projectRoot, ".cursor");
29428
- const routerPath = path60.join(cursorDir, "rules", "prjct.mdc");
29766
+ const cursorDir = path61.join(projectRoot, ".cursor");
29767
+ const routerPath = path61.join(cursorDir, "rules", "prjct.mdc");
29429
29768
  return await fileExists(cursorDir) && !await fileExists(routerPath);
29430
29769
  }
29431
29770
  async function installWindsurfProject(projectRoot) {
@@ -29436,26 +29775,26 @@ async function installWindsurfProject(projectRoot) {
29436
29775
  gitignoreUpdated: false
29437
29776
  };
29438
29777
  try {
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 });
29778
+ const windsurfDir = path61.join(projectRoot, ".windsurf");
29779
+ const rulesDir = path61.join(windsurfDir, "rules");
29780
+ const workflowsDir = path61.join(windsurfDir, "workflows");
29781
+ const routerDest = path61.join(rulesDir, "prjct.md");
29782
+ const routerSource = path61.join(PACKAGE_ROOT, "templates", "windsurf", "router.md");
29783
+ const windsurfWorkflowsSource = path61.join(PACKAGE_ROOT, "templates", "windsurf", "workflows");
29784
+ await fs57.mkdir(rulesDir, { recursive: true });
29785
+ await fs57.mkdir(workflowsDir, { recursive: true });
29447
29786
  if (await fileExists(routerSource)) {
29448
- await fs56.copyFile(routerSource, routerDest);
29787
+ await fs57.copyFile(routerSource, routerDest);
29449
29788
  result.rulesCreated = true;
29450
29789
  }
29451
29790
  if (await fileExists(windsurfWorkflowsSource)) {
29452
- const workflowFiles = (await fs56.readdir(windsurfWorkflowsSource)).filter(
29791
+ const workflowFiles = (await fs57.readdir(windsurfWorkflowsSource)).filter(
29453
29792
  (f) => f.endsWith(".md")
29454
29793
  );
29455
29794
  for (const file of workflowFiles) {
29456
- const src = path60.join(windsurfWorkflowsSource, file);
29457
- const dest = path60.join(workflowsDir, file);
29458
- await fs56.copyFile(src, dest);
29795
+ const src = path61.join(windsurfWorkflowsSource, file);
29796
+ const dest = path61.join(workflowsDir, file);
29797
+ await fs57.copyFile(src, dest);
29459
29798
  }
29460
29799
  result.workflowsCreated = workflowFiles.length > 0;
29461
29800
  }
@@ -29469,7 +29808,7 @@ async function installWindsurfProject(projectRoot) {
29469
29808
  }
29470
29809
  async function addWindsurfToGitignore(projectRoot) {
29471
29810
  try {
29472
- const gitignorePath = path60.join(projectRoot, ".gitignore");
29811
+ const gitignorePath = path61.join(projectRoot, ".gitignore");
29473
29812
  const entriesToAdd = [
29474
29813
  "# prjct Windsurf routers (regenerated per-developer)",
29475
29814
  ".windsurf/rules/prjct.md",
@@ -29484,7 +29823,7 @@ async function addWindsurfToGitignore(projectRoot) {
29484
29823
  let content = "";
29485
29824
  let configExists = false;
29486
29825
  try {
29487
- content = await fs56.readFile(gitignorePath, "utf-8");
29826
+ content = await fs57.readFile(gitignorePath, "utf-8");
29488
29827
  configExists = true;
29489
29828
  } catch (error) {
29490
29829
  if (!isNotFoundError(error)) {
@@ -29499,7 +29838,7 @@ async function addWindsurfToGitignore(projectRoot) {
29499
29838
  ${entriesToAdd.join("\n")}
29500
29839
  ` : `${entriesToAdd.join("\n")}
29501
29840
  `;
29502
- await fs56.writeFile(gitignorePath, newContent, "utf-8");
29841
+ await fs57.writeFile(gitignorePath, newContent, "utf-8");
29503
29842
  return true;
29504
29843
  } catch (error) {
29505
29844
  logger_default.warn(`Gitignore update warning: ${getErrorMessage2(error)}`);
@@ -29507,32 +29846,32 @@ ${entriesToAdd.join("\n")}
29507
29846
  }
29508
29847
  }
29509
29848
  async function hasWindsurfProject(projectRoot) {
29510
- return await fileExists(path60.join(projectRoot, ".windsurf"));
29849
+ return await fileExists(path61.join(projectRoot, ".windsurf"));
29511
29850
  }
29512
29851
  async function needsWindsurfRegeneration(projectRoot) {
29513
- const windsurfDir = path60.join(projectRoot, ".windsurf");
29514
- const routerPath = path60.join(windsurfDir, "rules", "prjct.md");
29852
+ const windsurfDir = path61.join(projectRoot, ".windsurf");
29853
+ const routerPath = path61.join(windsurfDir, "rules", "prjct.md");
29515
29854
  return await fileExists(windsurfDir) && !await fileExists(routerPath);
29516
29855
  }
29517
29856
  async function migrateProjectsCliVersion() {
29518
29857
  try {
29519
- const projectsDir = path60.join(os18.homedir(), ".prjct-cli", "projects");
29858
+ const projectsDir = path61.join(os18.homedir(), ".prjct-cli", "projects");
29520
29859
  if (!await fileExists(projectsDir)) {
29521
29860
  return;
29522
29861
  }
29523
- const projectDirs = (await fs56.readdir(projectsDir, { withFileTypes: true })).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
29862
+ const projectDirs = (await fs57.readdir(projectsDir, { withFileTypes: true })).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
29524
29863
  let migrated = 0;
29525
29864
  for (const projectId of projectDirs) {
29526
- const projectJsonPath = path60.join(projectsDir, projectId, "project.json");
29865
+ const projectJsonPath = path61.join(projectsDir, projectId, "project.json");
29527
29866
  if (!await fileExists(projectJsonPath)) {
29528
29867
  continue;
29529
29868
  }
29530
29869
  try {
29531
- const content = await fs56.readFile(projectJsonPath, "utf8");
29870
+ const content = await fs57.readFile(projectJsonPath, "utf8");
29532
29871
  const project = JSON.parse(content);
29533
29872
  if (project.cliVersion !== VERSION) {
29534
29873
  project.cliVersion = VERSION;
29535
- await fs56.writeFile(projectJsonPath, JSON.stringify(project, null, 2));
29874
+ await fs57.writeFile(projectJsonPath, JSON.stringify(project, null, 2));
29536
29875
  migrated++;
29537
29876
  }
29538
29877
  } catch (error) {
@@ -29554,7 +29893,7 @@ async function ensureStatusLineSettings(settingsPath, statusLinePath) {
29554
29893
  let settings = {};
29555
29894
  if (await fileExists(settingsPath)) {
29556
29895
  try {
29557
- settings = JSON.parse(await fs56.readFile(settingsPath, "utf8"));
29896
+ settings = JSON.parse(await fs57.readFile(settingsPath, "utf8"));
29558
29897
  } catch (error) {
29559
29898
  if (!(error instanceof SyntaxError)) {
29560
29899
  throw error;
@@ -29562,42 +29901,42 @@ async function ensureStatusLineSettings(settingsPath, statusLinePath) {
29562
29901
  }
29563
29902
  }
29564
29903
  settings.statusLine = { type: "command", command: statusLinePath };
29565
- await fs56.writeFile(settingsPath, JSON.stringify(settings, null, 2));
29904
+ await fs57.writeFile(settingsPath, JSON.stringify(settings, null, 2));
29566
29905
  }
29567
29906
  async function installStatusLine() {
29568
29907
  try {
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");
29908
+ const claudeDir = path61.join(os18.homedir(), ".claude");
29909
+ const settingsPath = path61.join(claudeDir, "settings.json");
29910
+ const claudeStatusLinePath = path61.join(claudeDir, "prjct-statusline.sh");
29911
+ const prjctStatusLineDir = path61.join(os18.homedir(), ".prjct-cli", "statusline");
29912
+ const prjctStatusLinePath = path61.join(prjctStatusLineDir, "statusline.sh");
29913
+ const prjctThemesDir = path61.join(prjctStatusLineDir, "themes");
29914
+ const prjctLibDir = path61.join(prjctStatusLineDir, "lib");
29915
+ const prjctComponentsDir = path61.join(prjctStatusLineDir, "components");
29916
+ const prjctConfigPath = path61.join(prjctStatusLineDir, "config.json");
29917
+ const assetsDir = path61.join(PACKAGE_ROOT, "assets", "statusline");
29918
+ const sourceScript = path61.join(assetsDir, "statusline.sh");
29919
+ const sourceThemeDir = path61.join(assetsDir, "themes");
29920
+ const sourceLibDir = path61.join(assetsDir, "lib");
29921
+ const sourceComponentsDir = path61.join(assetsDir, "components");
29922
+ const sourceConfigPath = path61.join(assetsDir, "default-config.json");
29584
29923
  if (!await fileExists(claudeDir)) {
29585
- await fs56.mkdir(claudeDir, { recursive: true });
29924
+ await fs57.mkdir(claudeDir, { recursive: true });
29586
29925
  }
29587
29926
  if (!await fileExists(prjctStatusLineDir)) {
29588
- await fs56.mkdir(prjctStatusLineDir, { recursive: true });
29927
+ await fs57.mkdir(prjctStatusLineDir, { recursive: true });
29589
29928
  }
29590
29929
  if (!await fileExists(prjctThemesDir)) {
29591
- await fs56.mkdir(prjctThemesDir, { recursive: true });
29930
+ await fs57.mkdir(prjctThemesDir, { recursive: true });
29592
29931
  }
29593
29932
  if (!await fileExists(prjctLibDir)) {
29594
- await fs56.mkdir(prjctLibDir, { recursive: true });
29933
+ await fs57.mkdir(prjctLibDir, { recursive: true });
29595
29934
  }
29596
29935
  if (!await fileExists(prjctComponentsDir)) {
29597
- await fs56.mkdir(prjctComponentsDir, { recursive: true });
29936
+ await fs57.mkdir(prjctComponentsDir, { recursive: true });
29598
29937
  }
29599
29938
  if (await fileExists(prjctStatusLinePath)) {
29600
- const existingContent = await fs56.readFile(prjctStatusLinePath, "utf8");
29939
+ const existingContent = await fs57.readFile(prjctStatusLinePath, "utf8");
29601
29940
  if (existingContent.includes("CLI_VERSION=")) {
29602
29941
  const versionMatch = existingContent.match(/CLI_VERSION="([^"]*)"/);
29603
29942
  if (versionMatch && versionMatch[1] !== VERSION) {
@@ -29605,7 +29944,7 @@ async function installStatusLine() {
29605
29944
  /CLI_VERSION="[^"]*"/,
29606
29945
  `CLI_VERSION="${VERSION}"`
29607
29946
  );
29608
- await fs56.writeFile(prjctStatusLinePath, updatedContent, { mode: 493 });
29947
+ await fs57.writeFile(prjctStatusLinePath, updatedContent, { mode: 493 });
29609
29948
  }
29610
29949
  await installStatusLineModules(sourceLibDir, prjctLibDir);
29611
29950
  await installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
@@ -29615,21 +29954,21 @@ async function installStatusLine() {
29615
29954
  }
29616
29955
  }
29617
29956
  if (await fileExists(sourceScript)) {
29618
- let scriptContent = await fs56.readFile(sourceScript, "utf8");
29957
+ let scriptContent = await fs57.readFile(sourceScript, "utf8");
29619
29958
  scriptContent = scriptContent.replace(/CLI_VERSION="[^"]*"/, `CLI_VERSION="${VERSION}"`);
29620
- await fs56.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
29959
+ await fs57.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
29621
29960
  await installStatusLineModules(sourceLibDir, prjctLibDir);
29622
29961
  await installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
29623
29962
  if (await fileExists(sourceThemeDir)) {
29624
- const themes = await fs56.readdir(sourceThemeDir);
29963
+ const themes = await fs57.readdir(sourceThemeDir);
29625
29964
  for (const theme of themes) {
29626
- const src = path60.join(sourceThemeDir, theme);
29627
- const dest = path60.join(prjctThemesDir, theme);
29628
- await fs56.copyFile(src, dest);
29965
+ const src = path61.join(sourceThemeDir, theme);
29966
+ const dest = path61.join(prjctThemesDir, theme);
29967
+ await fs57.copyFile(src, dest);
29629
29968
  }
29630
29969
  }
29631
29970
  if (!await fileExists(prjctConfigPath) && await fileExists(sourceConfigPath)) {
29632
- await fs56.copyFile(sourceConfigPath, prjctConfigPath);
29971
+ await fs57.copyFile(sourceConfigPath, prjctConfigPath);
29633
29972
  }
29634
29973
  } else {
29635
29974
  const scriptContent = `#!/bin/bash
@@ -29664,7 +30003,7 @@ if [ -f "$CONFIG" ]; then
29664
30003
  fi
29665
30004
  echo "prjct"
29666
30005
  `;
29667
- await fs56.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
30006
+ await fs57.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
29668
30007
  }
29669
30008
  await ensureStatusLineSymlink(claudeStatusLinePath, prjctStatusLinePath);
29670
30009
  await ensureStatusLineSettings(settingsPath, claudeStatusLinePath);
@@ -29676,10 +30015,10 @@ echo "prjct"
29676
30015
  }
29677
30016
  async function installContext7MCP() {
29678
30017
  try {
29679
- const claudeDir = path60.join(os18.homedir(), ".claude");
29680
- const mcpConfigPath = path60.join(claudeDir, "mcp.json");
30018
+ const claudeDir = path61.join(os18.homedir(), ".claude");
30019
+ const mcpConfigPath = path61.join(claudeDir, "mcp.json");
29681
30020
  if (!await fileExists(claudeDir)) {
29682
- await fs56.mkdir(claudeDir, { recursive: true });
30021
+ await fs57.mkdir(claudeDir, { recursive: true });
29683
30022
  }
29684
30023
  const context7Config = {
29685
30024
  mcpServers: {
@@ -29690,16 +30029,16 @@ async function installContext7MCP() {
29690
30029
  }
29691
30030
  };
29692
30031
  if (await fileExists(mcpConfigPath)) {
29693
- const existingContent = await fs56.readFile(mcpConfigPath, "utf-8");
30032
+ const existingContent = await fs57.readFile(mcpConfigPath, "utf-8");
29694
30033
  const existingConfig = JSON.parse(existingContent);
29695
30034
  if (existingConfig.mcpServers?.context7) {
29696
30035
  return;
29697
30036
  }
29698
30037
  existingConfig.mcpServers = existingConfig.mcpServers || {};
29699
30038
  existingConfig.mcpServers.context7 = context7Config.mcpServers.context7;
29700
- await fs56.writeFile(mcpConfigPath, JSON.stringify(existingConfig, null, 2), "utf-8");
30039
+ await fs57.writeFile(mcpConfigPath, JSON.stringify(existingConfig, null, 2), "utf-8");
29701
30040
  } else {
29702
- await fs56.writeFile(mcpConfigPath, JSON.stringify(context7Config, null, 2), "utf-8");
30041
+ await fs57.writeFile(mcpConfigPath, JSON.stringify(context7Config, null, 2), "utf-8");
29703
30042
  }
29704
30043
  } catch (error) {
29705
30044
  logger_default.warn(`Context7 MCP setup warning: ${getErrorMessage2(error)}`);
@@ -29709,34 +30048,34 @@ async function installStatusLineModules(sourceDir, destDir) {
29709
30048
  if (!await fileExists(sourceDir)) {
29710
30049
  return;
29711
30050
  }
29712
- const files = await fs56.readdir(sourceDir);
30051
+ const files = await fs57.readdir(sourceDir);
29713
30052
  for (const file of files) {
29714
30053
  if (file.endsWith(".sh")) {
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);
30054
+ const src = path61.join(sourceDir, file);
30055
+ const dest = path61.join(destDir, file);
30056
+ await fs57.copyFile(src, dest);
30057
+ await fs57.chmod(dest, 493);
29719
30058
  }
29720
30059
  }
29721
30060
  }
29722
30061
  async function ensureStatusLineSymlink(linkPath, targetPath) {
29723
30062
  try {
29724
30063
  if (await fileExists(linkPath)) {
29725
- const stats = await fs56.lstat(linkPath);
30064
+ const stats = await fs57.lstat(linkPath);
29726
30065
  if (stats.isSymbolicLink()) {
29727
- const existingTarget = await fs56.readlink(linkPath);
30066
+ const existingTarget = await fs57.readlink(linkPath);
29728
30067
  if (existingTarget === targetPath) {
29729
30068
  return;
29730
30069
  }
29731
30070
  }
29732
- await fs56.unlink(linkPath);
30071
+ await fs57.unlink(linkPath);
29733
30072
  }
29734
- await fs56.symlink(targetPath, linkPath);
30073
+ await fs57.symlink(targetPath, linkPath);
29735
30074
  } catch (_error) {
29736
30075
  try {
29737
30076
  if (await fileExists(targetPath)) {
29738
- await fs56.copyFile(targetPath, linkPath);
29739
- await fs56.chmod(linkPath, 493);
30077
+ await fs57.copyFile(targetPath, linkPath);
30078
+ await fs57.chmod(linkPath, 493);
29740
30079
  }
29741
30080
  } catch (copyError) {
29742
30081
  if (!isNotFoundError(copyError)) {
@@ -30151,7 +30490,7 @@ var init_registry2 = __esm({
30151
30490
  });
30152
30491
 
30153
30492
  // core/commands/analytics.ts
30154
- import path61 from "node:path";
30493
+ import path62 from "node:path";
30155
30494
  var AnalyticsCommands;
30156
30495
  var init_analytics = __esm({
30157
30496
  "core/commands/analytics.ts"() {
@@ -30178,7 +30517,7 @@ var init_analytics = __esm({
30178
30517
  output_default.failWithHint("NO_PROJECT_ID");
30179
30518
  return { success: false, error: "No project ID found" };
30180
30519
  }
30181
- const projectName = path61.basename(projectPath);
30520
+ const projectName = path62.basename(projectPath);
30182
30521
  const currentTask = await stateStorage.getCurrentTask(projectId);
30183
30522
  const queueTasks = await queueStorage.getActiveTasks(projectId);
30184
30523
  const shipped = await shippedStorage.getRecent(projectId, 5);
@@ -30430,8 +30769,8 @@ ${"\u2550".repeat(50)}
30430
30769
  });
30431
30770
 
30432
30771
  // core/commands/context.ts
30433
- import fs57 from "node:fs/promises";
30434
- import path62 from "node:path";
30772
+ import fs58 from "node:fs/promises";
30773
+ import path63 from "node:path";
30435
30774
  var ContextCommands, contextCommands;
30436
30775
  var init_context = __esm({
30437
30776
  "core/commands/context.ts"() {
@@ -30557,8 +30896,8 @@ var init_context = __esm({
30557
30896
  */
30558
30897
  async loadRepoAnalysis(globalPath) {
30559
30898
  try {
30560
- const analysisPath = path62.join(globalPath, "analysis", "repo-analysis.json");
30561
- const content = await fs57.readFile(analysisPath, "utf-8");
30899
+ const analysisPath = path63.join(globalPath, "analysis", "repo-analysis.json");
30900
+ const content = await fs58.readFile(analysisPath, "utf-8");
30562
30901
  const data = JSON.parse(content);
30563
30902
  return {
30564
30903
  ecosystem: data.ecosystem || "unknown",
@@ -30577,7 +30916,7 @@ var init_context = __esm({
30577
30916
  });
30578
30917
 
30579
30918
  // core/commands/cleanup.ts
30580
- import path63 from "node:path";
30919
+ import path64 from "node:path";
30581
30920
  async function cleanupMemory(projectPath) {
30582
30921
  const projectId = await config_manager_default.getProjectId(projectPath);
30583
30922
  const results = { rotated: [], totalSize: 0, freedSpace: 0 };
@@ -30593,7 +30932,7 @@ async function cleanupMemory(projectPath) {
30593
30932
  results.totalSize += sizeMB;
30594
30933
  const rotated = await jsonl_helper_exports.rotateJsonLinesIfNeeded(filePath, 10);
30595
30934
  if (rotated) {
30596
- results.rotated.push(path63.basename(filePath));
30935
+ results.rotated.push(path64.basename(filePath));
30597
30936
  results.freedSpace += sizeMB;
30598
30937
  }
30599
30938
  }
@@ -30700,7 +31039,7 @@ var init_cleanup = __esm({
30700
31039
  });
30701
31040
 
30702
31041
  // core/commands/design.ts
30703
- import path64 from "node:path";
31042
+ import path65 from "node:path";
30704
31043
  async function design(target = null, options = {}, projectPath = process.cwd()) {
30705
31044
  try {
30706
31045
  const designType = options.type || "architecture";
@@ -30712,7 +31051,7 @@ async function design(target = null, options = {}, projectPath = process.cwd())
30712
31051
  const designTarget = target || "system";
30713
31052
  output_default.spin(`designing ${designType}...`);
30714
31053
  const projectId = await config_manager_default.getProjectId(projectPath);
30715
- const designsPath = path64.join(
31054
+ const designsPath = path65.join(
30716
31055
  path_manager_default.getGlobalProjectPath(projectId),
30717
31056
  "planning",
30718
31057
  "designs"
@@ -30752,7 +31091,7 @@ async function design(target = null, options = {}, projectPath = process.cwd())
30752
31091
  break;
30753
31092
  }
30754
31093
  const designFileName = `${designType}-${designTarget.toLowerCase().replace(/\s+/g, "-")}.md`;
30755
- const designFilePath = path64.join(designsPath, designFileName);
31094
+ const designFilePath = path65.join(designsPath, designFileName);
30756
31095
  await file_helper_exports.writeFile(designFilePath, designContent);
30757
31096
  await memoryService.log(projectPath, "design_created", {
30758
31097
  type: designType,
@@ -30777,7 +31116,7 @@ var init_design = __esm({
30777
31116
  });
30778
31117
 
30779
31118
  // core/commands/snapshots.ts
30780
- import path65 from "node:path";
31119
+ import path66 from "node:path";
30781
31120
  async function recover(projectPath = process.cwd()) {
30782
31121
  try {
30783
31122
  const projectId = await config_manager_default.getProjectId(projectPath);
@@ -30829,7 +31168,7 @@ async function undo(projectPath = process.cwd()) {
30829
31168
  output_default.failWithHint("NO_PROJECT_ID");
30830
31169
  return { success: false, error: "No project ID found" };
30831
31170
  }
30832
- const snapshotsPath = path65.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
31171
+ const snapshotsPath = path66.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
30833
31172
  await file_helper_exports.ensureDir(snapshotsPath);
30834
31173
  const { execSync: execSync5 } = await import("node:child_process");
30835
31174
  try {
@@ -30847,7 +31186,7 @@ async function undo(projectPath = process.cwd()) {
30847
31186
  cwd: projectPath,
30848
31187
  encoding: "utf-8"
30849
31188
  });
30850
- const snapshotFile = path65.join(snapshotsPath, "history.json");
31189
+ const snapshotFile = path66.join(snapshotsPath, "history.json");
30851
31190
  let history2 = { snapshots: [], current: -1 };
30852
31191
  try {
30853
31192
  const content = await file_helper_exports.readFile(snapshotFile);
@@ -30887,8 +31226,8 @@ async function redo(projectPath = process.cwd()) {
30887
31226
  output_default.failWithHint("NO_PROJECT_ID");
30888
31227
  return { success: false, error: "No project ID found" };
30889
31228
  }
30890
- const snapshotsPath = path65.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
30891
- const snapshotFile = path65.join(snapshotsPath, "history.json");
31229
+ const snapshotsPath = path66.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
31230
+ const snapshotFile = path66.join(snapshotsPath, "history.json");
30892
31231
  let history2;
30893
31232
  try {
30894
31233
  const content = await file_helper_exports.readFile(snapshotFile);
@@ -30947,8 +31286,8 @@ async function history(projectPath = process.cwd()) {
30947
31286
  output_default.failWithHint("NO_PROJECT_ID");
30948
31287
  return { success: false, error: "No project ID found" };
30949
31288
  }
30950
- const snapshotsPath = path65.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
30951
- const snapshotFile = path65.join(snapshotsPath, "history.json");
31289
+ const snapshotsPath = path66.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
31290
+ const snapshotFile = path66.join(snapshotsPath, "history.json");
30952
31291
  let snapshotHistory;
30953
31292
  try {
30954
31293
  const content = await file_helper_exports.readFile(snapshotFile);
@@ -31151,8 +31490,8 @@ ${chalk16.cyan("Performance Report")} ${chalk16.dim(`(last ${days} days)`)}`);
31151
31490
  });
31152
31491
 
31153
31492
  // core/commands/setup.ts
31154
- import fs58 from "node:fs/promises";
31155
- import path66 from "node:path";
31493
+ import fs59 from "node:fs/promises";
31494
+ import path67 from "node:path";
31156
31495
  import chalk17 from "chalk";
31157
31496
  var SetupCommands;
31158
31497
  var init_setup2 = __esm({
@@ -31281,7 +31620,7 @@ Please install it first:
31281
31620
  try {
31282
31621
  const claudeDir = path_manager_default.getClaudeDir();
31283
31622
  const settingsPath = path_manager_default.getClaudeSettingsPath();
31284
- const statusLinePath = path66.join(claudeDir, "prjct-statusline.sh");
31623
+ const statusLinePath = path67.join(claudeDir, "prjct-statusline.sh");
31285
31624
  const scriptContent = `#!/bin/bash
31286
31625
  # prjct Status Line for Claude Code
31287
31626
  # Shows version update notifications and current task
@@ -31339,11 +31678,11 @@ fi
31339
31678
  # Default: show prjct branding
31340
31679
  echo "\u26A1 prjct"
31341
31680
  `;
31342
- await fs58.writeFile(statusLinePath, scriptContent, { mode: 493 });
31681
+ await fs59.writeFile(statusLinePath, scriptContent, { mode: 493 });
31343
31682
  let settings = {};
31344
31683
  if (await fileExists(settingsPath)) {
31345
31684
  try {
31346
- settings = JSON.parse(await fs58.readFile(settingsPath, "utf8"));
31685
+ settings = JSON.parse(await fs59.readFile(settingsPath, "utf8"));
31347
31686
  } catch (_error) {
31348
31687
  }
31349
31688
  }
@@ -31351,7 +31690,7 @@ echo "\u26A1 prjct"
31351
31690
  type: "command",
31352
31691
  command: statusLinePath
31353
31692
  };
31354
- await fs58.writeFile(settingsPath, JSON.stringify(settings, null, 2));
31693
+ await fs59.writeFile(settingsPath, JSON.stringify(settings, null, 2));
31355
31694
  return { success: true };
31356
31695
  } catch (error) {
31357
31696
  return { success: false, error: getErrorMessage2(error) };
@@ -31407,18 +31746,18 @@ echo "\u26A1 prjct"
31407
31746
  });
31408
31747
 
31409
31748
  // core/utils/project-commands.ts
31410
- import path67 from "node:path";
31749
+ import path68 from "node:path";
31411
31750
  async function detectPackageManager(projectPath, pkg) {
31412
31751
  const declared = pkg?.packageManager?.trim().toLowerCase();
31413
31752
  if (declared?.startsWith("pnpm@")) return "pnpm";
31414
31753
  if (declared?.startsWith("yarn@")) return "yarn";
31415
31754
  if (declared?.startsWith("bun@")) return "bun";
31416
31755
  if (declared?.startsWith("npm@")) 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";
31756
+ if (await fileExists2(path68.join(projectPath, "pnpm-lock.yaml"))) return "pnpm";
31757
+ if (await fileExists2(path68.join(projectPath, "yarn.lock"))) return "yarn";
31758
+ if (await fileExists2(path68.join(projectPath, "bun.lockb"))) return "bun";
31759
+ if (await fileExists2(path68.join(projectPath, "bun.lock"))) return "bun";
31760
+ if (await fileExists2(path68.join(projectPath, "package-lock.json"))) return "npm";
31422
31761
  return "npm";
31423
31762
  }
31424
31763
  function pmRun(pm, scriptName) {
@@ -31434,7 +31773,7 @@ function pmTest(pm) {
31434
31773
  return "npm test";
31435
31774
  }
31436
31775
  async function detectProjectCommands(projectPath) {
31437
- const pkgPath = path67.join(projectPath, "package.json");
31776
+ const pkgPath = path68.join(projectPath, "package.json");
31438
31777
  const pkg = await readJson(pkgPath, null);
31439
31778
  if (pkg) {
31440
31779
  const pm = await detectPackageManager(projectPath, pkg);
@@ -31451,27 +31790,27 @@ async function detectProjectCommands(projectPath) {
31451
31790
  }
31452
31791
  return result;
31453
31792
  }
31454
- if (await fileExists2(path67.join(projectPath, "pytest.ini"))) {
31793
+ if (await fileExists2(path68.join(projectPath, "pytest.ini"))) {
31455
31794
  return { stack: "python", test: { tool: "pytest", command: "pytest" } };
31456
31795
  }
31457
- const pyproject = await readFile(path67.join(projectPath, "pyproject.toml"), "");
31796
+ const pyproject = await readFile(path68.join(projectPath, "pyproject.toml"), "");
31458
31797
  if (pyproject.includes("[tool.pytest") || pyproject.includes("pytest")) {
31459
31798
  return { stack: "python", test: { tool: "pytest", command: "pytest" } };
31460
31799
  }
31461
- if (await fileExists2(path67.join(projectPath, "Cargo.toml"))) {
31800
+ if (await fileExists2(path68.join(projectPath, "Cargo.toml"))) {
31462
31801
  return { stack: "rust", test: { tool: "cargo", command: "cargo test" } };
31463
31802
  }
31464
- if (await fileExists2(path67.join(projectPath, "go.mod"))) {
31803
+ if (await fileExists2(path68.join(projectPath, "go.mod"))) {
31465
31804
  return { stack: "go", test: { tool: "go", command: "go test ./..." } };
31466
31805
  }
31467
31806
  const files = await listFiles(projectPath);
31468
31807
  if (files.some((f) => f.endsWith(".sln") || f.endsWith(".csproj") || f.endsWith(".fsproj"))) {
31469
31808
  return { stack: "dotnet", test: { tool: "dotnet", command: "dotnet test" } };
31470
31809
  }
31471
- if (await fileExists2(path67.join(projectPath, "pom.xml"))) {
31810
+ if (await fileExists2(path68.join(projectPath, "pom.xml"))) {
31472
31811
  return { stack: "java", test: { tool: "maven", command: "mvn test" } };
31473
31812
  }
31474
- if (await fileExists2(path67.join(projectPath, "gradlew")) && (await fileExists2(path67.join(projectPath, "build.gradle")) || await fileExists2(path67.join(projectPath, "build.gradle.kts")))) {
31813
+ if (await fileExists2(path68.join(projectPath, "gradlew")) && (await fileExists2(path68.join(projectPath, "build.gradle")) || await fileExists2(path68.join(projectPath, "build.gradle.kts")))) {
31475
31814
  return { stack: "java", test: { tool: "gradle", command: "./gradlew test" } };
31476
31815
  }
31477
31816
  return { stack: "unknown" };
@@ -31646,7 +31985,7 @@ var init_workflow_preferences = __esm({
31646
31985
  });
31647
31986
 
31648
31987
  // core/commands/shipping.ts
31649
- import path68 from "node:path";
31988
+ import path69 from "node:path";
31650
31989
  var ShippingCommands;
31651
31990
  var init_shipping = __esm({
31652
31991
  "core/commands/shipping.ts"() {
@@ -31792,7 +32131,7 @@ ${result.stderr}`.trim();
31792
32131
  */
31793
32132
  async _bumpVersion(projectPath) {
31794
32133
  try {
31795
- const pkgPath = path68.join(projectPath, "package.json");
32134
+ const pkgPath = path69.join(projectPath, "package.json");
31796
32135
  const pkg = await file_helper_exports.readJson(pkgPath, { version: "0.0.0" });
31797
32136
  const oldVersion = pkg?.version || "0.0.0";
31798
32137
  const [major, minor, patch] = oldVersion.split(".").map(Number);
@@ -31814,7 +32153,7 @@ ${result.stderr}`.trim();
31814
32153
  */
31815
32154
  async _updateChangelog(feature, version, projectPath) {
31816
32155
  try {
31817
- const changelogPath = path68.join(projectPath, "CHANGELOG.md");
32156
+ const changelogPath = path69.join(projectPath, "CHANGELOG.md");
31818
32157
  const changelog = await file_helper_exports.readFile(changelogPath, "# Changelog\n\n");
31819
32158
  const entry = `## [${version}] - ${date_helper_exports.formatDate(/* @__PURE__ */ new Date())}
31820
32159
 
@@ -32858,11 +33197,11 @@ var init_linear = __esm({
32858
33197
  });
32859
33198
 
32860
33199
  // core/utils/project-credentials.ts
32861
- import fs59 from "node:fs/promises";
33200
+ import fs60 from "node:fs/promises";
32862
33201
  import os19 from "node:os";
32863
- import path69 from "node:path";
33202
+ import path70 from "node:path";
32864
33203
  function getCredentialsPath(projectId) {
32865
- return path69.join(os19.homedir(), ".prjct-cli", "projects", projectId, "config", "credentials.json");
33204
+ return path70.join(os19.homedir(), ".prjct-cli", "projects", projectId, "config", "credentials.json");
32866
33205
  }
32867
33206
  async function getProjectCredentials(projectId) {
32868
33207
  const credPath = getCredentialsPath(projectId);
@@ -32870,7 +33209,7 @@ async function getProjectCredentials(projectId) {
32870
33209
  return {};
32871
33210
  }
32872
33211
  try {
32873
- return JSON.parse(await fs59.readFile(credPath, "utf-8"));
33212
+ return JSON.parse(await fs60.readFile(credPath, "utf-8"));
32874
33213
  } catch (error) {
32875
33214
  console.error("[project-credentials] Failed to read credentials:", getErrorMessage2(error));
32876
33215
  return {};
@@ -33542,7 +33881,7 @@ var require_package = __commonJS({
33542
33881
  "package.json"(exports, module) {
33543
33882
  module.exports = {
33544
33883
  name: "prjct-cli",
33545
- version: "1.17.0",
33884
+ version: "1.18.0",
33546
33885
  description: "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
33547
33886
  main: "core/index.ts",
33548
33887
  bin: {
@@ -33649,7 +33988,7 @@ var require_package = __commonJS({
33649
33988
  // core/index.ts
33650
33989
  var core_exports = {};
33651
33990
  import os20 from "node:os";
33652
- import path70 from "node:path";
33991
+ import path71 from "node:path";
33653
33992
  import chalk20 from "chalk";
33654
33993
  async function main() {
33655
33994
  const [commandName, ...rawArgs] = process.argv.slice(2);
@@ -33754,7 +34093,8 @@ async function main() {
33754
34093
  preview: options.preview === true || options["dry-run"] === true,
33755
34094
  yes: options.yes === true,
33756
34095
  json: options.json === true,
33757
- package: options.package ? String(options.package) : void 0
34096
+ package: options.package ? String(options.package) : void 0,
34097
+ full: options.full === true
33758
34098
  }), "sync"),
33759
34099
  seal: /* @__PURE__ */ __name(() => commands.seal(process.cwd(), { json: options.json === true }), "seal"),
33760
34100
  verify: /* @__PURE__ */ __name(() => commands.verify(process.cwd(), { json: options.json === true }), "verify"),
@@ -33862,13 +34202,13 @@ function parseCommandArgs(_cmd, rawArgs) {
33862
34202
  }
33863
34203
  async function displayVersion(version) {
33864
34204
  const detection = await detectAllProviders();
33865
- const claudeCommandPath = path70.join(os20.homedir(), ".claude", "commands", "p.md");
33866
- const geminiCommandPath = path70.join(os20.homedir(), ".gemini", "commands", "p.toml");
34205
+ const claudeCommandPath = path71.join(os20.homedir(), ".claude", "commands", "p.md");
34206
+ const geminiCommandPath = path71.join(os20.homedir(), ".gemini", "commands", "p.toml");
33867
34207
  const [claudeConfigured, geminiConfigured, cursorConfigured, cursorExists] = await Promise.all([
33868
34208
  fileExists(claudeCommandPath),
33869
34209
  fileExists(geminiCommandPath),
33870
- fileExists(path70.join(process.cwd(), ".cursor", "commands", "sync.md")),
33871
- fileExists(path70.join(process.cwd(), ".cursor"))
34210
+ fileExists(path71.join(process.cwd(), ".cursor", "commands", "sync.md")),
34211
+ fileExists(path71.join(process.cwd(), ".cursor"))
33872
34212
  ]);
33873
34213
  const antigravityDetection = await detectAntigravity();
33874
34214
  console.log(`
@@ -34007,7 +34347,7 @@ init_ai_provider();
34007
34347
  init_config_manager();
34008
34348
  init_editors_config();
34009
34349
  import os21 from "node:os";
34010
- import path71 from "node:path";
34350
+ import path72 from "node:path";
34011
34351
  import chalk21 from "chalk";
34012
34352
 
34013
34353
  // core/server/server.ts
@@ -34828,13 +35168,13 @@ async function checkRoutersInstalled() {
34828
35168
  const home = os21.homedir();
34829
35169
  const detection = await detectAllProviders();
34830
35170
  if (detection.claude.installed) {
34831
- const claudeRouter = path71.join(home, ".claude", "commands", "p.md");
35171
+ const claudeRouter = path72.join(home, ".claude", "commands", "p.md");
34832
35172
  if (!await fileExists(claudeRouter)) {
34833
35173
  return false;
34834
35174
  }
34835
35175
  }
34836
35176
  if (detection.gemini.installed) {
34837
- const geminiRouter = path71.join(home, ".gemini", "commands", "p.toml");
35177
+ const geminiRouter = path72.join(home, ".gemini", "commands", "p.toml");
34838
35178
  if (!await fileExists(geminiRouter)) {
34839
35179
  return false;
34840
35180
  }
@@ -34975,7 +35315,7 @@ if (args[0] === "start" || args[0] === "setup") {
34975
35315
  console.error('No prjct project found. Run "prjct init" first.');
34976
35316
  process.exitCode = 1;
34977
35317
  } else {
34978
- const linearCliPath = path71.join(__dirname, "..", "core", "cli", "linear.ts");
35318
+ const linearCliPath = path72.join(__dirname, "..", "core", "cli", "linear.ts");
34979
35319
  const linearArgs = ["--project", projectId, ...args.slice(1)];
34980
35320
  const child = spawn("bun", [linearCliPath, ...linearArgs], {
34981
35321
  stdio: "inherit",
@@ -35002,12 +35342,12 @@ if (args[0] === "start" || args[0] === "setup") {
35002
35342
  windsurfDetected,
35003
35343
  windsurfConfigured
35004
35344
  ] = await Promise.all([
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"))
35345
+ fileExists(path72.join(home, ".claude", "commands", "p.md")),
35346
+ fileExists(path72.join(home, ".gemini", "commands", "p.toml")),
35347
+ fileExists(path72.join(cwd, ".cursor")),
35348
+ fileExists(path72.join(cwd, ".cursor", "rules", "prjct.mdc")),
35349
+ fileExists(path72.join(cwd, ".windsurf")),
35350
+ fileExists(path72.join(cwd, ".windsurf", "rules", "prjct.md"))
35011
35351
  ]);
35012
35352
  console.log(`
35013
35353
  ${chalk21.cyan("p/")} prjct v${VERSION}
@@ -35046,7 +35386,7 @@ ${chalk21.dim("Run 'prjct init' to configure (Cursor/Windsurf IDE)")}
35046
35386
  ${chalk21.cyan("https://prjct.app")}
35047
35387
  `);
35048
35388
  } else {
35049
- const configPath = path71.join(os21.homedir(), ".prjct-cli", "config", "installed-editors.json");
35389
+ const configPath = path72.join(os21.homedir(), ".prjct-cli", "config", "installed-editors.json");
35050
35390
  const routersInstalled = await checkRoutersInstalled();
35051
35391
  if (!await fileExists(configPath) || !routersInstalled) {
35052
35392
  console.log(`