prjct-cli 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,12 +1,45 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.2.2] - 2026-02-06
4
+
5
+ ### Performance
6
+
7
+ - convert execSync to async in ground-truth.ts (PRJ-92) (#113)
8
+ - convert execSync to async in ground-truth.ts (PRJ-92)
9
+
10
+
3
11
  ## [1.2.1] - 2026-02-06
4
12
 
13
+ ### Performance
14
+
15
+ - **Convert execSync to async in ground-truth.ts (PRJ-92)**: Replaced blocking execSync with promisify(exec) in verifyShip
16
+
5
17
  ### Bug Fixes
6
18
 
7
19
  - replace raw ANSI codes with chalk library (PRJ-132) (#111)
8
- - replace raw ANSI codes with chalk library (PRJ-132)
9
20
 
21
+ ### Implementation Details
22
+
23
+ Replaced the single `execSync('git status --porcelain')` call in `verifyShip()` with `await execAsync()` using `promisify(exec)` from `node:util`. The rest of `ground-truth.ts` already used async `fs.promises` — this was the last synchronous call blocking the event loop.
24
+
25
+ ### Learnings
26
+
27
+ - `exec` returns `{stdout, stderr}` object vs `execSync` returning a string directly — must destructure
28
+ - `promisify(exec)` is simpler than `spawn` for short-lived commands that return stdout
29
+ - Terminal control sequences (cursor movement) are separate from color/formatting — chalk doesn't handle them
30
+
31
+ ### Test Plan
32
+
33
+ #### For QA
34
+ 1. Run `bun run build && bun run typecheck` — zero errors
35
+ 2. Trigger `verifyShip` path — verify async git status check works
36
+ 3. Test with uncommitted changes — verify warning still appears
37
+ 4. Test in non-git directory — verify graceful fallback (`gitAvailable = false`)
38
+
39
+ #### For Users
40
+ **What changed:** Internal performance improvement — git status check in ground-truth verifier is now async
41
+ **How to use:** No change needed — improvement is internal
42
+ **Breaking changes:** None
10
43
 
11
44
  ## [1.2.0] - 2026-02-06
12
45
 
@@ -11,14 +11,17 @@
11
11
  * Source: Devin, Cursor, Augment Code patterns
12
12
  */
13
13
 
14
- import { execSync } from 'node:child_process'
14
+ import { exec } from 'node:child_process'
15
15
  import fs from 'node:fs/promises'
16
16
  import os from 'node:os'
17
17
  import path from 'node:path'
18
+ import { promisify } from 'node:util'
18
19
 
19
20
  import type { GroundTruthContext, VerificationResult, Verifier } from '../types'
20
21
  import { isNotFoundError } from '../types/fs'
21
22
 
23
+ const execAsync = promisify(exec)
24
+
22
25
  // =============================================================================
23
26
  // Utilities
24
27
  // =============================================================================
@@ -163,9 +166,8 @@ export async function verifyShip(context: GroundTruthContext): Promise<Verificat
163
166
 
164
167
  // 1. Check for uncommitted changes
165
168
  try {
166
- const gitStatus = execSync('git status --porcelain', {
169
+ const { stdout: gitStatus } = await execAsync('git status --porcelain', {
167
170
  cwd: context.projectPath,
168
- encoding: 'utf-8',
169
171
  })
170
172
  actual.hasUncommittedChanges = gitStatus.trim().length > 0
171
173
  actual.uncommittedFiles = gitStatus.trim().split('\n').filter(Boolean).length
@@ -11,7 +11,6 @@
11
11
  * @module services/hooks-service
12
12
  */
13
13
 
14
- import { execSync } from 'node:child_process'
15
14
  import fs from 'node:fs'
16
15
  import path from 'node:path'
17
16
  import chalk from 'chalk'
@@ -209,7 +208,7 @@ ${sectionName}:
209
208
  )
210
209
  } else {
211
210
  // Append new section
212
- content = content.trimEnd() + '\n' + hookBlock
211
+ content = `${content.trimEnd()}\n${hookBlock}`
213
212
  }
214
213
  }
215
214
 
@@ -262,7 +261,7 @@ function installDirect(projectPath: string, hooks: HookName[]): boolean {
262
261
  continue // Already installed
263
262
  }
264
263
  // Append to existing hook
265
- fs.appendFileSync(hookPath, '\n# prjct auto-sync\n' + script.split('\n').slice(1).join('\n'))
264
+ fs.appendFileSync(hookPath, `\n# prjct auto-sync\n${script.split('\n').slice(1).join('\n')}`)
266
265
  } else {
267
266
  fs.writeFileSync(hookPath, script, { mode: 0o755 })
268
267
  }
@@ -291,7 +290,7 @@ function uninstallLefthook(projectPath: string): boolean {
291
290
  // Clean up empty sections
292
291
  content = content.replace(/^(post-commit|post-checkout):\s*commands:\s*$/gm, '')
293
292
 
294
- fs.writeFileSync(configPath, content.trimEnd() + '\n', 'utf-8')
293
+ fs.writeFileSync(configPath, `${content.trimEnd()}\n`, 'utf-8')
295
294
  return true
296
295
  }
297
296
 
@@ -5549,7 +5549,8 @@ ${sectionName}:
5549
5549
  fail_text: "prjct sync failed (non-blocking)"`
5550
5550
  );
5551
5551
  } else {
5552
- content = content.trimEnd() + "\n" + hookBlock;
5552
+ content = `${content.trimEnd()}
5553
+ ${hookBlock}`;
5553
5554
  }
5554
5555
  }
5555
5556
  fs15.writeFileSync(configPath, content, "utf-8");
@@ -5585,7 +5586,9 @@ function installDirect(projectPath, hooks) {
5585
5586
  if (existing.includes("prjct sync")) {
5586
5587
  continue;
5587
5588
  }
5588
- fs15.appendFileSync(hookPath, "\n# prjct auto-sync\n" + script.split("\n").slice(1).join("\n"));
5589
+ fs15.appendFileSync(hookPath, `
5590
+ # prjct auto-sync
5591
+ ${script.split("\n").slice(1).join("\n")}`);
5589
5592
  } else {
5590
5593
  fs15.writeFileSync(hookPath, script, { mode: 493 });
5591
5594
  }
@@ -5599,7 +5602,8 @@ function uninstallLefthook(projectPath) {
5599
5602
  let content = fs15.readFileSync(configPath, "utf-8");
5600
5603
  content = content.replace(/\s*prjct-sync-[\w-]+:[\s\S]*?(?=\n\S|\n*$)/g, "");
5601
5604
  content = content.replace(/^(post-commit|post-checkout):\s*commands:\s*$/gm, "");
5602
- fs15.writeFileSync(configPath, content.trimEnd() + "\n", "utf-8");
5605
+ fs15.writeFileSync(configPath, `${content.trimEnd()}
5606
+ `, "utf-8");
5603
5607
  return true;
5604
5608
  }
5605
5609
  function uninstallHusky(projectPath) {
@@ -7352,10 +7356,11 @@ var init_context_builder = __esm({
7352
7356
  });
7353
7357
 
7354
7358
  // core/agentic/ground-truth.ts
7355
- import { execSync as execSync3 } from "node:child_process";
7359
+ import { exec as exec5 } from "node:child_process";
7356
7360
  import fs19 from "node:fs/promises";
7357
7361
  import os6 from "node:os";
7358
7362
  import path18 from "node:path";
7363
+ import { promisify as promisify5 } from "node:util";
7359
7364
  function formatDuration2(ms) {
7360
7365
  const hours = Math.floor(ms / (1e3 * 60 * 60));
7361
7366
  const minutes = Math.floor(ms % (1e3 * 60 * 60) / (1e3 * 60));
@@ -7455,9 +7460,8 @@ async function verifyShip(context2) {
7455
7460
  const recommendations = [];
7456
7461
  const actual = {};
7457
7462
  try {
7458
- const gitStatus = execSync3("git status --porcelain", {
7459
- cwd: context2.projectPath,
7460
- encoding: "utf-8"
7463
+ const { stdout: gitStatus } = await execAsync("git status --porcelain", {
7464
+ cwd: context2.projectPath
7461
7465
  });
7462
7466
  actual.hasUncommittedChanges = gitStatus.trim().length > 0;
7463
7467
  actual.uncommittedFiles = gitStatus.trim().split("\n").filter(Boolean).length;
@@ -7839,11 +7843,12 @@ async function prepareCommand(commandName, context2, state) {
7839
7843
  function requiresVerification(commandName) {
7840
7844
  return ["done", "ship", "feature", "spec", "now", "init", "sync", "analyze"].includes(commandName);
7841
7845
  }
7842
- var verifiers, ground_truth_default;
7846
+ var execAsync, verifiers, ground_truth_default;
7843
7847
  var init_ground_truth = __esm({
7844
7848
  "core/agentic/ground-truth.ts"() {
7845
7849
  "use strict";
7846
7850
  init_fs();
7851
+ execAsync = promisify5(exec5);
7847
7852
  __name(formatDuration2, "formatDuration");
7848
7853
  __name(escapeRegex, "escapeRegex");
7849
7854
  __name(formatWarnings, "formatWarnings");
@@ -14143,14 +14148,14 @@ When fragmenting tasks:
14143
14148
  });
14144
14149
 
14145
14150
  // core/agentic/tool-registry.ts
14146
- import { exec as exec5 } from "node:child_process";
14151
+ import { exec as exec6 } from "node:child_process";
14147
14152
  import fs28 from "node:fs/promises";
14148
- import { promisify as promisify5 } from "node:util";
14149
- var execAsync, toolRegistry, tool_registry_default;
14153
+ import { promisify as promisify6 } from "node:util";
14154
+ var execAsync2, toolRegistry, tool_registry_default;
14150
14155
  var init_tool_registry = __esm({
14151
14156
  "core/agentic/tool-registry.ts"() {
14152
14157
  "use strict";
14153
- execAsync = promisify5(exec5);
14158
+ execAsync2 = promisify6(exec6);
14154
14159
  toolRegistry = {
14155
14160
  tools: /* @__PURE__ */ new Map(),
14156
14161
  /**
@@ -14205,7 +14210,7 @@ var init_tool_registry = __esm({
14205
14210
  "Bash",
14206
14211
  async (command) => {
14207
14212
  try {
14208
- const { stdout, stderr } = await execAsync(command);
14213
+ const { stdout, stderr } = await execAsync2(command);
14209
14214
  return { stdout, stderr };
14210
14215
  } catch (error) {
14211
14216
  const err = error;
@@ -16095,7 +16100,7 @@ var init_file_scorer = __esm({
16095
16100
  });
16096
16101
 
16097
16102
  // core/services/dependency-validator.ts
16098
- import { execSync as execSync4 } from "node:child_process";
16103
+ import { execSync as execSync3 } from "node:child_process";
16099
16104
  var TOOLS, DependencyValidator, DependencyError, dependencyValidator;
16100
16105
  var init_dependency_validator = __esm({
16101
16106
  "core/services/dependency-validator.ts"() {
@@ -16255,7 +16260,7 @@ ${hints}`
16255
16260
  // ==========================================================================
16256
16261
  executeCheck(definition) {
16257
16262
  try {
16258
- const output = execSync4(definition.command, {
16263
+ const output = execSync3(definition.command, {
16259
16264
  encoding: "utf-8",
16260
16265
  stdio: ["pipe", "pipe", "pipe"],
16261
16266
  timeout: 5e3
@@ -16280,7 +16285,7 @@ ${hints}`
16280
16285
  }
16281
16286
  checkUnknownTool(toolName) {
16282
16287
  try {
16283
- execSync4(`${toolName} --version`, {
16288
+ execSync3(`${toolName} --version`, {
16284
16289
  encoding: "utf-8",
16285
16290
  stdio: ["pipe", "pipe", "pipe"],
16286
16291
  timeout: 5e3
@@ -16288,7 +16293,7 @@ ${hints}`
16288
16293
  return { available: true };
16289
16294
  } catch {
16290
16295
  try {
16291
- execSync4(`${toolName} -v`, {
16296
+ execSync3(`${toolName} -v`, {
16292
16297
  encoding: "utf-8",
16293
16298
  stdio: ["pipe", "pipe", "pipe"],
16294
16299
  timeout: 5e3
@@ -16338,15 +16343,15 @@ ${hints}`
16338
16343
  });
16339
16344
 
16340
16345
  // core/services/git-analyzer.ts
16341
- import { exec as exec6 } from "node:child_process";
16342
- import { promisify as promisify6 } from "node:util";
16343
- var execAsync2;
16346
+ import { exec as exec7 } from "node:child_process";
16347
+ import { promisify as promisify7 } from "node:util";
16348
+ var execAsync3;
16344
16349
  var init_git_analyzer = __esm({
16345
16350
  "core/services/git-analyzer.ts"() {
16346
16351
  "use strict";
16347
16352
  init_constants();
16348
16353
  init_dependency_validator();
16349
- execAsync2 = promisify6(exec6);
16354
+ execAsync3 = promisify7(exec7);
16350
16355
  }
16351
16356
  });
16352
16357
 
@@ -17021,16 +17026,16 @@ ${agent.description}`;
17021
17026
  });
17022
17027
 
17023
17028
  // core/services/project-index.ts
17024
- import { exec as exec7 } from "node:child_process";
17025
- import { promisify as promisify7 } from "node:util";
17026
- var execAsync3;
17029
+ import { exec as exec8 } from "node:child_process";
17030
+ import { promisify as promisify8 } from "node:util";
17031
+ var execAsync4;
17027
17032
  var init_project_index = __esm({
17028
17033
  "core/services/project-index.ts"() {
17029
17034
  "use strict";
17030
17035
  init_index_storage();
17031
17036
  init_date_helper();
17032
17037
  init_file_scorer();
17033
- execAsync3 = promisify7(exec7);
17038
+ execAsync4 = promisify8(exec8);
17034
17039
  }
17035
17040
  });
17036
17041
 
@@ -17699,10 +17704,10 @@ var init_wizard = __esm({
17699
17704
  });
17700
17705
 
17701
17706
  // core/context/generator.ts
17702
- import { exec as exec8 } from "node:child_process";
17707
+ import { exec as exec9 } from "node:child_process";
17703
17708
  import fs34 from "node:fs/promises";
17704
17709
  import path35 from "node:path";
17705
- import { promisify as promisify8 } from "node:util";
17710
+ import { promisify as promisify9 } from "node:util";
17706
17711
  async function generateContext(projectId, repoPath) {
17707
17712
  const _globalPath = path_manager_default.getGlobalProjectPath(projectId);
17708
17713
  const contextPath = path_manager_default.getContextPath(projectId);
@@ -17760,17 +17765,17 @@ async function getGitData(repoPath) {
17760
17765
  recentCommits: []
17761
17766
  };
17762
17767
  try {
17763
- const { stdout: branch } = await execAsync4("git branch --show-current", { cwd: repoPath });
17768
+ const { stdout: branch } = await execAsync5("git branch --show-current", { cwd: repoPath });
17764
17769
  data.branch = branch.trim() || "main";
17765
- const { stdout: commits } = await execAsync4("git rev-list --count HEAD", { cwd: repoPath });
17770
+ const { stdout: commits } = await execAsync5("git rev-list --count HEAD", { cwd: repoPath });
17766
17771
  data.commits = parseInt(commits.trim(), 10) || 0;
17767
- const { stdout: contributors } = await execAsync4("git shortlog -sn --all | wc -l", {
17772
+ const { stdout: contributors } = await execAsync5("git shortlog -sn --all | wc -l", {
17768
17773
  cwd: repoPath
17769
17774
  });
17770
17775
  data.contributors = parseInt(contributors.trim(), 10) || 0;
17771
- const { stdout: status } = await execAsync4("git status --porcelain", { cwd: repoPath });
17776
+ const { stdout: status } = await execAsync5("git status --porcelain", { cwd: repoPath });
17772
17777
  data.hasChanges = status.trim().length > 0;
17773
- const { stdout: log } = await execAsync4(
17778
+ const { stdout: log } = await execAsync5(
17774
17779
  'git log --oneline -10 --pretty=format:"%h|%s|%ad" --date=short',
17775
17780
  { cwd: repoPath }
17776
17781
  );
@@ -17919,13 +17924,13 @@ async function generateSummaryMd(contextPath, project, gitData, pkgData) {
17919
17924
  `;
17920
17925
  await fs34.writeFile(path35.join(contextPath, "summary.md"), content, "utf-8");
17921
17926
  }
17922
- var execAsync4;
17927
+ var execAsync5;
17923
17928
  var init_generator = __esm({
17924
17929
  "core/context/generator.ts"() {
17925
17930
  "use strict";
17926
17931
  init_path_manager();
17927
17932
  init_storage2();
17928
- execAsync4 = promisify8(exec8);
17933
+ execAsync5 = promisify9(exec9);
17929
17934
  __name(generateContext, "generateContext");
17930
17935
  __name(getGitData, "getGitData");
17931
17936
  __name(getPackageData, "getPackageData");
@@ -17940,13 +17945,13 @@ var init_generator = __esm({
17940
17945
  import { exec as execCallback5 } from "node:child_process";
17941
17946
  import fs35 from "node:fs/promises";
17942
17947
  import path36 from "node:path";
17943
- import { promisify as promisify9 } from "node:util";
17944
- var exec9, CodebaseAnalyzer, analyzer, analyzer_default2;
17948
+ import { promisify as promisify10 } from "node:util";
17949
+ var exec10, CodebaseAnalyzer, analyzer, analyzer_default2;
17945
17950
  var init_analyzer2 = __esm({
17946
17951
  "core/domain/analyzer.ts"() {
17947
17952
  "use strict";
17948
17953
  init_fs();
17949
- exec9 = promisify9(execCallback5);
17954
+ exec10 = promisify10(execCallback5);
17950
17955
  CodebaseAnalyzer = class {
17951
17956
  static {
17952
17957
  __name(this, "CodebaseAnalyzer");
@@ -18092,7 +18097,7 @@ var init_analyzer2 = __esm({
18092
18097
  */
18093
18098
  async getFileExtensions() {
18094
18099
  try {
18095
- const { stdout } = await exec9(
18100
+ const { stdout } = await exec10(
18096
18101
  'find . -type f ! -path "*/node_modules/*" ! -path "*/.git/*" ! -path "*/dist/*" ! -path "*/.next/*" | sed "s/.*\\./\\./" | sort | uniq -c | sort -rn',
18097
18102
  { cwd: this.projectPath }
18098
18103
  );
@@ -18158,7 +18163,7 @@ var init_analyzer2 = __esm({
18158
18163
  */
18159
18164
  async getGitLog(limit = 50) {
18160
18165
  try {
18161
- const { stdout } = await exec9(`git log -n ${limit} --pretty=format:"%h|%an|%ar|%s"`, {
18166
+ const { stdout } = await exec10(`git log -n ${limit} --pretty=format:"%h|%an|%ar|%s"`, {
18162
18167
  cwd: this.projectPath
18163
18168
  });
18164
18169
  return stdout;
@@ -18171,13 +18176,13 @@ var init_analyzer2 = __esm({
18171
18176
  */
18172
18177
  async getGitStats() {
18173
18178
  try {
18174
- const { stdout: totalCommits } = await exec9("git rev-list --count HEAD", {
18179
+ const { stdout: totalCommits } = await exec10("git rev-list --count HEAD", {
18175
18180
  cwd: this.projectPath
18176
18181
  });
18177
- const { stdout: contributors } = await exec9('git log --format="%an" | sort -u | wc -l', {
18182
+ const { stdout: contributors } = await exec10('git log --format="%an" | sort -u | wc -l', {
18178
18183
  cwd: this.projectPath
18179
18184
  });
18180
- const { stdout: firstCommit } = await exec9(
18185
+ const { stdout: firstCommit } = await exec10(
18181
18186
  'git log --reverse --pretty=format:"%ar" | head -1',
18182
18187
  {
18183
18188
  cwd: this.projectPath
@@ -18201,7 +18206,7 @@ var init_analyzer2 = __esm({
18201
18206
  */
18202
18207
  async countFiles() {
18203
18208
  try {
18204
- const { stdout } = await exec9(
18209
+ const { stdout } = await exec10(
18205
18210
  'find . -type f ! -path "*/node_modules/*" ! -path "*/.git/*" ! -path "*/dist/*" | wc -l',
18206
18211
  { cwd: this.projectPath }
18207
18212
  );
@@ -18243,7 +18248,7 @@ var init_analyzer2 = __esm({
18243
18248
  */
18244
18249
  async findFiles(pattern) {
18245
18250
  try {
18246
- const { stdout } = await exec9(
18251
+ const { stdout } = await exec10(
18247
18252
  `find . -type f -name "${pattern}" ! -path "*/node_modules/*" ! -path "*/.git/*"`,
18248
18253
  { cwd: this.projectPath }
18249
18254
  );
@@ -19903,16 +19908,16 @@ var init_project_service = __esm({
19903
19908
  });
19904
19909
 
19905
19910
  // core/services/staleness-checker.ts
19906
- import { exec as exec10 } from "node:child_process";
19911
+ import { exec as exec11 } from "node:child_process";
19907
19912
  import fs37 from "node:fs/promises";
19908
19913
  import path39 from "node:path";
19909
- import { promisify as promisify10 } from "node:util";
19910
- var execAsync5, DEFAULT_CONFIG, StalenessChecker, createStalenessChecker;
19914
+ import { promisify as promisify11 } from "node:util";
19915
+ var execAsync6, DEFAULT_CONFIG, StalenessChecker, createStalenessChecker;
19911
19916
  var init_staleness_checker = __esm({
19912
19917
  "core/services/staleness-checker.ts"() {
19913
19918
  "use strict";
19914
19919
  init_path_manager();
19915
- execAsync5 = promisify10(exec10);
19920
+ execAsync6 = promisify11(exec11);
19916
19921
  DEFAULT_CONFIG = {
19917
19922
  commitThreshold: 10,
19918
19923
  dayThreshold: 3,
@@ -19965,7 +19970,7 @@ var init_staleness_checker = __esm({
19965
19970
  status.lastSyncCommit = projectJson.lastSyncCommit || null;
19966
19971
  const lastSync = projectJson.lastSync;
19967
19972
  try {
19968
- const { stdout } = await execAsync5("git rev-parse --short HEAD", {
19973
+ const { stdout } = await execAsync6("git rev-parse --short HEAD", {
19969
19974
  cwd: this.projectPath
19970
19975
  });
19971
19976
  status.currentCommit = stdout.trim();
@@ -19983,7 +19988,7 @@ var init_staleness_checker = __esm({
19983
19988
  return status;
19984
19989
  }
19985
19990
  try {
19986
- const { stdout } = await execAsync5(`git rev-list --count ${status.lastSyncCommit}..HEAD`, {
19991
+ const { stdout } = await execAsync6(`git rev-list --count ${status.lastSyncCommit}..HEAD`, {
19987
19992
  cwd: this.projectPath
19988
19993
  });
19989
19994
  status.commitsSinceSync = parseInt(stdout.trim(), 10) || 0;
@@ -20000,7 +20005,7 @@ var init_staleness_checker = __esm({
20000
20005
  );
20001
20006
  }
20002
20007
  try {
20003
- const { stdout } = await execAsync5(`git diff --name-only ${status.lastSyncCommit}..HEAD`, {
20008
+ const { stdout } = await execAsync6(`git diff --name-only ${status.lastSyncCommit}..HEAD`, {
20004
20009
  cwd: this.projectPath
20005
20010
  });
20006
20011
  status.changedFiles = stdout.trim().split("\n").filter(Boolean);
@@ -20332,7 +20337,7 @@ var init_formatters = __esm({
20332
20337
  });
20333
20338
 
20334
20339
  // core/ai-tools/registry.ts
20335
- import { execSync as execSync5 } from "node:child_process";
20340
+ import { execSync as execSync4 } from "node:child_process";
20336
20341
  import fs38 from "node:fs";
20337
20342
  import os11 from "node:os";
20338
20343
  import path40 from "node:path";
@@ -20341,7 +20346,7 @@ function getAIToolConfig(id) {
20341
20346
  }
20342
20347
  function commandExists(cmd) {
20343
20348
  try {
20344
- execSync5(`which ${cmd}`, { stdio: "ignore" });
20349
+ execSync4(`which ${cmd}`, { stdio: "ignore" });
20345
20350
  return true;
20346
20351
  } catch {
20347
20352
  return false;
@@ -21153,11 +21158,11 @@ var init_stack_detector = __esm({
21153
21158
  });
21154
21159
 
21155
21160
  // core/services/sync-service.ts
21156
- import { exec as exec11 } from "node:child_process";
21161
+ import { exec as exec12 } from "node:child_process";
21157
21162
  import fs43 from "node:fs/promises";
21158
21163
  import path45 from "node:path";
21159
- import { promisify as promisify11 } from "node:util";
21160
- var execAsync6, SyncService, syncService;
21164
+ import { promisify as promisify12 } from "node:util";
21165
+ var execAsync7, SyncService, syncService;
21161
21166
  var init_sync_service = __esm({
21162
21167
  "core/services/sync-service.ts"() {
21163
21168
  "use strict";
@@ -21170,7 +21175,7 @@ var init_sync_service = __esm({
21170
21175
  init_context_generator();
21171
21176
  init_local_state_generator();
21172
21177
  init_stack_detector();
21173
- execAsync6 = promisify11(exec11);
21178
+ execAsync7 = promisify12(exec12);
21174
21179
  SyncService = class {
21175
21180
  static {
21176
21181
  __name(this, "SyncService");
@@ -21327,19 +21332,19 @@ var init_sync_service = __esm({
21327
21332
  weeklyCommits: 0
21328
21333
  };
21329
21334
  try {
21330
- const { stdout: branch } = await execAsync6("git branch --show-current", {
21335
+ const { stdout: branch } = await execAsync7("git branch --show-current", {
21331
21336
  cwd: this.projectPath
21332
21337
  });
21333
21338
  data.branch = branch.trim() || "main";
21334
- const { stdout: commits } = await execAsync6("git rev-list --count HEAD", {
21339
+ const { stdout: commits } = await execAsync7("git rev-list --count HEAD", {
21335
21340
  cwd: this.projectPath
21336
21341
  });
21337
21342
  data.commits = parseInt(commits.trim(), 10) || 0;
21338
- const { stdout: contributors } = await execAsync6("git shortlog -sn --all | wc -l", {
21343
+ const { stdout: contributors } = await execAsync7("git shortlog -sn --all | wc -l", {
21339
21344
  cwd: this.projectPath
21340
21345
  });
21341
21346
  data.contributors = parseInt(contributors.trim(), 10) || 0;
21342
- const { stdout: status } = await execAsync6("git status --porcelain", {
21347
+ const { stdout: status } = await execAsync7("git status --porcelain", {
21343
21348
  cwd: this.projectPath
21344
21349
  });
21345
21350
  const lines = status.trim().split("\n").filter(Boolean);
@@ -21355,7 +21360,7 @@ var init_sync_service = __esm({
21355
21360
  data.untrackedFiles.push(file);
21356
21361
  }
21357
21362
  }
21358
- const { stdout: log } = await execAsync6(
21363
+ const { stdout: log } = await execAsync7(
21359
21364
  'git log --oneline -20 --pretty=format:"%h|%s|%ad" --date=short',
21360
21365
  { cwd: this.projectPath }
21361
21366
  );
@@ -21363,7 +21368,7 @@ var init_sync_service = __esm({
21363
21368
  const [hash, message, date] = line.split("|");
21364
21369
  return { hash, message, date };
21365
21370
  });
21366
- const { stdout: weekly } = await execAsync6('git log --oneline --since="1 week ago" | wc -l', {
21371
+ const { stdout: weekly } = await execAsync7('git log --oneline --since="1 week ago" | wc -l', {
21367
21372
  cwd: this.projectPath
21368
21373
  });
21369
21374
  data.weeklyCommits = parseInt(weekly.trim(), 10) || 0;
@@ -21385,7 +21390,7 @@ var init_sync_service = __esm({
21385
21390
  frameworks: []
21386
21391
  };
21387
21392
  try {
21388
- const { stdout } = await execAsync6(
21393
+ const { stdout } = await execAsync7(
21389
21394
  'find . -type f \\( -name "*.js" -o -name "*.ts" -o -name "*.tsx" -o -name "*.py" -o -name "*.go" -o -name "*.rs" \\) -not -path "./node_modules/*" -not -path "./.git/*" | wc -l',
21390
21395
  { cwd: this.projectPath }
21391
21396
  );
@@ -21985,7 +21990,7 @@ __export(uninstall_exports, {
21985
21990
  UninstallCommands: () => UninstallCommands,
21986
21991
  uninstall: () => uninstall
21987
21992
  });
21988
- import { execSync as execSync6 } from "node:child_process";
21993
+ import { execSync as execSync5 } from "node:child_process";
21989
21994
  import fsSync2 from "node:fs";
21990
21995
  import fs44 from "node:fs/promises";
21991
21996
  import os12 from "node:os";
@@ -22033,7 +22038,7 @@ function detectInstallation() {
22033
22038
  npm: false
22034
22039
  };
22035
22040
  try {
22036
- const result = execSync6("brew list prjct-cli 2>/dev/null", { encoding: "utf-8" });
22041
+ const result = execSync5("brew list prjct-cli 2>/dev/null", { encoding: "utf-8" });
22037
22042
  if (result) {
22038
22043
  info.homebrew = true;
22039
22044
  info.homebrewFormula = "prjct-cli";
@@ -22041,7 +22046,7 @@ function detectInstallation() {
22041
22046
  } catch {
22042
22047
  }
22043
22048
  try {
22044
- const result = execSync6("npm list -g prjct-cli --depth=0 2>/dev/null", { encoding: "utf-8" });
22049
+ const result = execSync5("npm list -g prjct-cli --depth=0 2>/dev/null", { encoding: "utf-8" });
22045
22050
  if (result.includes("prjct-cli")) {
22046
22051
  info.npm = true;
22047
22052
  }
@@ -22209,7 +22214,7 @@ async function performUninstall(items, installation, options) {
22209
22214
  if (installation.homebrew && installation.homebrewFormula) {
22210
22215
  try {
22211
22216
  if (!options.dryRun) {
22212
- execSync6(`brew uninstall ${installation.homebrewFormula}`, { stdio: "pipe" });
22217
+ execSync5(`brew uninstall ${installation.homebrewFormula}`, { stdio: "pipe" });
22213
22218
  }
22214
22219
  deleted.push("Homebrew: prjct-cli");
22215
22220
  } catch (error) {
@@ -22219,7 +22224,7 @@ async function performUninstall(items, installation, options) {
22219
22224
  if (installation.npm) {
22220
22225
  try {
22221
22226
  if (!options.dryRun) {
22222
- execSync6("npm uninstall -g prjct-cli", { stdio: "pipe" });
22227
+ execSync5("npm uninstall -g prjct-cli", { stdio: "pipe" });
22223
22228
  }
22224
22229
  deleted.push("npm: prjct-cli");
22225
22230
  } catch (error) {
@@ -23255,7 +23260,7 @@ __export(setup_exports, {
23255
23260
  needsWindsurfRegeneration: () => needsWindsurfRegeneration,
23256
23261
  run: () => run
23257
23262
  });
23258
- import { execSync as execSync7 } from "node:child_process";
23263
+ import { execSync as execSync6 } from "node:child_process";
23259
23264
  import fs45 from "node:fs";
23260
23265
  import os13 from "node:os";
23261
23266
  import path48 from "node:path";
@@ -23279,7 +23284,7 @@ async function installAICLI(provider) {
23279
23284
  try {
23280
23285
  console.log(chalk15.yellow(`\u{1F4E6} ${provider.displayName} not found. Installing...`));
23281
23286
  console.log("");
23282
- execSync7(`npm install -g ${packageName}`, {
23287
+ execSync6(`npm install -g ${packageName}`, {
23283
23288
  stdio: "inherit",
23284
23289
  timeout: getTimeout("NPM_INSTALL")
23285
23290
  });
@@ -24970,9 +24975,9 @@ async function undo(projectPath = process.cwd()) {
24970
24975
  }
24971
24976
  const snapshotsPath = path53.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
24972
24977
  await file_helper_exports.ensureDir(snapshotsPath);
24973
- const { execSync: execSync8 } = await import("node:child_process");
24978
+ const { execSync: execSync7 } = await import("node:child_process");
24974
24979
  try {
24975
- const status = execSync8("git status --porcelain", {
24980
+ const status = execSync7("git status --porcelain", {
24976
24981
  cwd: projectPath,
24977
24982
  encoding: "utf-8"
24978
24983
  }).trim();
@@ -24982,7 +24987,7 @@ async function undo(projectPath = process.cwd()) {
24982
24987
  }
24983
24988
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
24984
24989
  const stashMessage = `prjct-undo-${timestamp}`;
24985
- execSync8(`git stash push -m "${stashMessage}"`, {
24990
+ execSync7(`git stash push -m "${stashMessage}"`, {
24986
24991
  cwd: projectPath,
24987
24992
  encoding: "utf-8"
24988
24993
  });
@@ -25043,9 +25048,9 @@ async function redo(projectPath = process.cwd()) {
25043
25048
  output_default.warn("nothing to redo");
25044
25049
  return { success: false, message: "Nothing to redo" };
25045
25050
  }
25046
- const { execSync: execSync8 } = await import("node:child_process");
25051
+ const { execSync: execSync7 } = await import("node:child_process");
25047
25052
  try {
25048
- const stashList = execSync8("git stash list", {
25053
+ const stashList = execSync7("git stash list", {
25049
25054
  cwd: projectPath,
25050
25055
  encoding: "utf-8"
25051
25056
  }).trim();
@@ -25058,7 +25063,7 @@ async function redo(projectPath = process.cwd()) {
25058
25063
  output_default.warn("no prjct undo point found");
25059
25064
  return { success: false, message: "No prjct undo point found" };
25060
25065
  }
25061
- execSync8("git stash pop", {
25066
+ execSync7("git stash pop", {
25062
25067
  cwd: projectPath,
25063
25068
  encoding: "utf-8"
25064
25069
  });
@@ -25529,8 +25534,8 @@ var init_project_commands = __esm({
25529
25534
  });
25530
25535
 
25531
25536
  // core/workflow/workflow-preferences.ts
25532
- import { exec as exec12 } from "node:child_process";
25533
- import { promisify as promisify12 } from "node:util";
25537
+ import { exec as exec13 } from "node:child_process";
25538
+ import { promisify as promisify13 } from "node:util";
25534
25539
  import chalk17 from "chalk";
25535
25540
  function prefKey(hook, command) {
25536
25541
  return `workflow:${hook}_${command}`;
@@ -25602,7 +25607,7 @@ async function runWorkflowHooks(projectId, phase, command, options = {}) {
25602
25607
  ${chalk17.dim(`Running ${phase}-${command}: ${action}`)}`);
25603
25608
  try {
25604
25609
  const startTime = Date.now();
25605
- await execAsync7(action, {
25610
+ await execAsync8(action, {
25606
25611
  timeout: 6e4,
25607
25612
  cwd: options.projectPath || process.cwd(),
25608
25613
  env: { ...process.env }
@@ -25666,12 +25671,12 @@ Set one: "p. workflow antes de ship corre los tests"`;
25666
25671
  lines.push(chalk17.dim('Remove: "p. workflow quita el hook de ship"'));
25667
25672
  return lines.join("\n");
25668
25673
  }
25669
- var execAsync7, sessionPreferences, oncePreferences;
25674
+ var execAsync8, sessionPreferences, oncePreferences;
25670
25675
  var init_workflow_preferences = __esm({
25671
25676
  "core/workflow/workflow-preferences.ts"() {
25672
25677
  "use strict";
25673
25678
  init_memory_system();
25674
- execAsync7 = promisify12(exec12);
25679
+ execAsync8 = promisify13(exec13);
25675
25680
  sessionPreferences = /* @__PURE__ */ new Map();
25676
25681
  oncePreferences = /* @__PURE__ */ new Map();
25677
25682
  __name(prefKey, "prefKey");
@@ -25952,14 +25957,14 @@ var init_cache2 = __esm({
25952
25957
  });
25953
25958
 
25954
25959
  // core/utils/keychain.ts
25955
- import { exec as exec13 } from "node:child_process";
25956
- import { promisify as promisify13 } from "node:util";
25960
+ import { exec as exec14 } from "node:child_process";
25961
+ import { promisify as promisify14 } from "node:util";
25957
25962
  async function getCredential(key) {
25958
25963
  if (process.platform !== "darwin") {
25959
25964
  return getEnvFallback(key);
25960
25965
  }
25961
25966
  try {
25962
- const { stdout } = await execAsync8(
25967
+ const { stdout } = await execAsync9(
25963
25968
  `security find-generic-password -s "${SERVICE_NAME}" -a "${key}" -w 2>/dev/null`
25964
25969
  );
25965
25970
  return stdout.trim() || null;
@@ -25975,11 +25980,11 @@ function getEnvFallback(key) {
25975
25980
  const envVar = envMap[key];
25976
25981
  return process.env[envVar] || null;
25977
25982
  }
25978
- var execAsync8, SERVICE_NAME;
25983
+ var execAsync9, SERVICE_NAME;
25979
25984
  var init_keychain = __esm({
25980
25985
  "core/utils/keychain.ts"() {
25981
25986
  "use strict";
25982
- execAsync8 = promisify13(exec13);
25987
+ execAsync9 = promisify14(exec14);
25983
25988
  SERVICE_NAME = "prjct-cli";
25984
25989
  __name(getCredential, "getCredential");
25985
25990
  __name(getEnvFallback, "getEnvFallback");
@@ -27334,7 +27339,7 @@ var require_package = __commonJS({
27334
27339
  "package.json"(exports, module) {
27335
27340
  module.exports = {
27336
27341
  name: "prjct-cli",
27337
- version: "1.2.1",
27342
+ version: "1.2.2",
27338
27343
  description: "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
27339
27344
  main: "core/index.ts",
27340
27345
  bin: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prjct-cli",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
5
5
  "main": "core/index.ts",
6
6
  "bin": {