@paths.design/caws-cli 8.0.1 → 8.2.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.
Files changed (112) hide show
  1. package/README.md +5 -6
  2. package/dist/commands/archive.d.ts +1 -0
  3. package/dist/commands/archive.d.ts.map +1 -1
  4. package/dist/commands/archive.js +114 -6
  5. package/dist/commands/burnup.d.ts.map +1 -1
  6. package/dist/commands/burnup.js +109 -10
  7. package/dist/commands/diagnose.js +1 -1
  8. package/dist/commands/init.d.ts.map +1 -1
  9. package/dist/commands/init.js +185 -39
  10. package/dist/commands/mode.d.ts +2 -1
  11. package/dist/commands/mode.d.ts.map +1 -1
  12. package/dist/commands/mode.js +24 -14
  13. package/dist/commands/provenance.d.ts.map +1 -1
  14. package/dist/commands/provenance.js +216 -93
  15. package/dist/commands/quality-gates.d.ts.map +1 -1
  16. package/dist/commands/quality-gates.js +3 -1
  17. package/dist/commands/specs.d.ts.map +1 -1
  18. package/dist/commands/specs.js +184 -6
  19. package/dist/commands/status.d.ts.map +1 -1
  20. package/dist/commands/status.js +134 -10
  21. package/dist/commands/templates.js +2 -2
  22. package/dist/commands/worktree.d.ts +7 -0
  23. package/dist/commands/worktree.d.ts.map +1 -0
  24. package/dist/commands/worktree.js +136 -0
  25. package/dist/config/lite-scope.d.ts +33 -0
  26. package/dist/config/lite-scope.d.ts.map +1 -0
  27. package/dist/config/lite-scope.js +158 -0
  28. package/dist/config/modes.d.ts +90 -51
  29. package/dist/config/modes.d.ts.map +1 -1
  30. package/dist/config/modes.js +26 -0
  31. package/dist/error-handler.d.ts +3 -16
  32. package/dist/error-handler.d.ts.map +1 -1
  33. package/dist/error-handler.js +6 -98
  34. package/dist/generators/jest-config-generator.d.ts +32 -0
  35. package/dist/generators/jest-config-generator.d.ts.map +1 -0
  36. package/dist/generators/jest-config-generator.js +242 -0
  37. package/dist/index.js +40 -7
  38. package/dist/minimal-cli.js +3 -1
  39. package/dist/scaffold/claude-hooks.d.ts +28 -0
  40. package/dist/scaffold/claude-hooks.d.ts.map +1 -0
  41. package/dist/scaffold/claude-hooks.js +344 -0
  42. package/dist/scaffold/index.d.ts +2 -0
  43. package/dist/scaffold/index.d.ts.map +1 -1
  44. package/dist/scaffold/index.js +96 -76
  45. package/dist/templates/.caws/schemas/scope.schema.json +52 -0
  46. package/dist/templates/.caws/schemas/working-spec.schema.json +1 -1
  47. package/dist/templates/.caws/schemas/worktrees.schema.json +36 -0
  48. package/dist/templates/.claude/README.md +190 -0
  49. package/dist/templates/.claude/hooks/audit.sh +96 -0
  50. package/dist/templates/.claude/hooks/block-dangerous.sh +123 -0
  51. package/dist/templates/.claude/hooks/lite-sprawl-check.sh +117 -0
  52. package/dist/templates/.claude/hooks/naming-check.sh +97 -0
  53. package/dist/templates/.claude/hooks/quality-check.sh +68 -0
  54. package/dist/templates/.claude/hooks/scan-secrets.sh +85 -0
  55. package/dist/templates/.claude/hooks/scope-guard.sh +192 -0
  56. package/dist/templates/.claude/hooks/simplification-guard.sh +92 -0
  57. package/dist/templates/.claude/hooks/validate-spec.sh +76 -0
  58. package/dist/templates/.claude/settings.json +95 -0
  59. package/dist/templates/.cursor/README.md +0 -3
  60. package/dist/templates/.github/copilot-instructions.md +82 -0
  61. package/dist/templates/.junie/guidelines.md +73 -0
  62. package/dist/templates/.vscode/launch.json +0 -27
  63. package/dist/templates/.windsurf/rules/caws-quality-standards.md +54 -0
  64. package/dist/templates/CLAUDE.md +101 -0
  65. package/dist/templates/agents.md +73 -1016
  66. package/dist/templates/docs/README.md +5 -5
  67. package/dist/test-analysis.d.ts +50 -1
  68. package/dist/test-analysis.d.ts.map +1 -1
  69. package/dist/test-analysis.js +203 -10
  70. package/dist/utils/error-categories.d.ts +52 -0
  71. package/dist/utils/error-categories.d.ts.map +1 -0
  72. package/dist/utils/error-categories.js +210 -0
  73. package/dist/utils/gitignore-updater.d.ts +1 -1
  74. package/dist/utils/gitignore-updater.d.ts.map +1 -1
  75. package/dist/utils/gitignore-updater.js +4 -0
  76. package/dist/utils/ide-detection.js +133 -0
  77. package/dist/utils/quality-gates-utils.d.ts +49 -0
  78. package/dist/utils/quality-gates-utils.d.ts.map +1 -0
  79. package/dist/utils/quality-gates-utils.js +402 -0
  80. package/dist/utils/typescript-detector.d.ts +8 -5
  81. package/dist/utils/typescript-detector.d.ts.map +1 -1
  82. package/dist/utils/typescript-detector.js +36 -90
  83. package/dist/validation/spec-validation.d.ts.map +1 -1
  84. package/dist/validation/spec-validation.js +59 -6
  85. package/dist/worktree/worktree-manager.d.ts +54 -0
  86. package/dist/worktree/worktree-manager.d.ts.map +1 -0
  87. package/dist/worktree/worktree-manager.js +378 -0
  88. package/package.json +9 -3
  89. package/templates/.caws/schemas/scope.schema.json +52 -0
  90. package/templates/.caws/schemas/working-spec.schema.json +1 -1
  91. package/templates/.caws/schemas/worktrees.schema.json +36 -0
  92. package/templates/.claude/README.md +190 -0
  93. package/templates/.claude/hooks/audit.sh +96 -0
  94. package/templates/.claude/hooks/block-dangerous.sh +123 -0
  95. package/templates/.claude/hooks/lite-sprawl-check.sh +117 -0
  96. package/templates/.claude/hooks/naming-check.sh +97 -0
  97. package/templates/.claude/hooks/quality-check.sh +68 -0
  98. package/templates/.claude/hooks/scan-secrets.sh +85 -0
  99. package/templates/.claude/hooks/scope-guard.sh +192 -0
  100. package/templates/.claude/hooks/simplification-guard.sh +92 -0
  101. package/templates/.claude/hooks/validate-spec.sh +76 -0
  102. package/templates/.claude/settings.json +95 -0
  103. package/templates/.cursor/README.md +0 -3
  104. package/templates/.github/copilot-instructions.md +82 -0
  105. package/templates/.junie/guidelines.md +73 -0
  106. package/templates/.vscode/launch.json +0 -27
  107. package/templates/.windsurf/rules/caws-quality-standards.md +54 -0
  108. package/templates/AGENTS.md +104 -0
  109. package/templates/CLAUDE.md +101 -0
  110. package/templates/docs/README.md +5 -5
  111. package/templates/.github/copilot/instructions.md +0 -311
  112. package/templates/agents.md +0 -1047
@@ -8,8 +8,9 @@ import { getCurrentMode } from "../config/modes";
8
8
  import { setCurrentMode } from "../config/modes";
9
9
  /**
10
10
  * Display current mode status
11
+ * @param {string} currentMode - The current mode to display
11
12
  */
12
- export function displayCurrentMode(): void;
13
+ export function displayCurrentMode(currentMode: string): void;
13
14
  /**
14
15
  * Display mode details
15
16
  * @param {string} mode - Mode to display
@@ -1 +1 @@
1
- {"version":3,"file":"mode.d.ts","sourceRoot":"","sources":["../../src/commands/mode.js"],"names":[],"mappings":"AAuHA;;;;GAIG;AACH,oCAHW,MAAM,+BAgIhB;;;AAvOD;;GAEG;AACH,2CAOC;AAED;;;GAGG;AACH,yCAFW,MAAM,QA+ChB;AAED;;;GAGG;AACH,4CAFa,OAAO,CAAC,MAAM,CAAC,CAkC3B"}
1
+ {"version":3,"file":"mode.d.ts","sourceRoot":"","sources":["../../src/commands/mode.js"],"names":[],"mappings":"AA0IA;;;;GAIG;AACH,oCAHW,MAAM,+BAuHhB;;;AAjPD;;;GAGG;AACH,gDAFW,MAAM,QA2BhB;AAED;;;GAGG;AACH,yCAFW,MAAM,QA+ChB;AAED;;;GAGG;AACH,4CAFa,OAAO,CAAC,MAAM,CAAC,CAkC3B"}
@@ -18,13 +18,32 @@ const {
18
18
 
19
19
  /**
20
20
  * Display current mode status
21
+ * @param {string} currentMode - The current mode to display
21
22
  */
22
- function displayCurrentMode() {
23
+ function displayCurrentMode(currentMode) {
24
+ const tier = getTier(currentMode);
25
+
23
26
  console.log(chalk.bold.cyan('\n🔧 CAWS Current Mode'));
24
27
  console.log(chalk.cyan('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
25
28
 
26
- // This will be implemented when we load the current mode
27
- console.log(chalk.yellow('Mode display will be implemented...'));
29
+ console.log(chalk.bold(`Active Mode: ${tier.icon} ${tier.color(currentMode)}`));
30
+ console.log(chalk.gray(`Description: ${tier.description}`));
31
+ console.log('');
32
+
33
+ // Quality requirements
34
+ console.log(chalk.bold('Quality Requirements:'));
35
+ console.log(chalk.gray(` Test Coverage: ≥${tier.qualityRequirements.testCoverage}%`));
36
+ console.log(chalk.gray(` Mutation Score: ≥${tier.qualityRequirements.mutationScore}%`));
37
+ console.log(chalk.gray(` Contracts: ${tier.qualityRequirements.contracts}`));
38
+ console.log('');
39
+
40
+ // Risk tiers supported
41
+ console.log(chalk.bold('Supported Risk Tiers:'));
42
+ tier.riskTiers.forEach((riskTier) => {
43
+ const riskColor =
44
+ riskTier === 'T1' ? chalk.red : riskTier === 'T2' ? chalk.yellow : chalk.green;
45
+ console.log(chalk.gray(` ${riskColor(riskTier)}`));
46
+ });
28
47
  console.log('');
29
48
  }
30
49
 
@@ -128,21 +147,12 @@ async function modeCommand(action, options = {}) {
128
147
  switch (action) {
129
148
  case 'current': {
130
149
  const currentMode = await getCurrentMode();
131
- displayCurrentMode();
132
-
133
- const tier = getTier(currentMode);
134
- console.log(chalk.bold(`Current Mode: ${tier.icon} ${tier.color(currentMode)}`));
135
- console.log(chalk.gray(`Description: ${tier.description}`));
136
- console.log(
137
- chalk.gray(
138
- `Quality: ${tier.qualityRequirements.testCoverage}% coverage, ${tier.qualityRequirements.mutationScore}% mutation`
139
- )
140
- );
150
+ displayCurrentMode(currentMode);
141
151
 
142
152
  return outputResult({
143
153
  command: 'mode current',
144
154
  mode: currentMode,
145
- tier: tier,
155
+ tier: getTier(currentMode),
146
156
  });
147
157
  }
148
158
 
@@ -1 +1 @@
1
- {"version":3,"file":"provenance.d.ts","sourceRoot":"","sources":["../../src/commands/provenance.js"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,8CAHW,MAAM,8BA+BhB;AAED;;;GAGG;AACH,8DA4EC;AAED;;;GAGG;AACH,4DAyEC;AAED;;;GAGG;AACH,8DA8CC;AA6iBD;;;GAGG;AACH,4DAmEC;AAzcD;;;GAGG;AACH,0DAwEC"}
1
+ {"version":3,"file":"provenance.d.ts","sourceRoot":"","sources":["../../src/commands/provenance.js"],"names":[],"mappings":"AA2CA;;;;GAIG;AACH,8CAHW,MAAM,8BA+BhB;AAED;;;GAGG;AACH,8DAuEC;AAED;;;GAGG;AACH,4DAyEC;AAED;;;GAGG;AACH,8DA8CC;AAgnBD;;;GAGG;AACH,4DAmEC;AA/cD;;;GAGG;AACH,0DAwEC"}
@@ -4,12 +4,43 @@
4
4
  * @author @darianrosebrook
5
5
  */
6
6
 
7
+ /* global fetch */
8
+
7
9
  const fs = require('fs-extra');
8
10
  const path = require('path');
9
11
  const crypto = require('crypto');
10
12
  const yaml = require('js-yaml');
13
+ const { execSync } = require('child_process');
11
14
  const { commandWrapper } = require('../utils/command-wrapper');
12
15
 
16
+ /**
17
+ * Get quality gates status from saved report
18
+ * @returns {Object} Quality gates status
19
+ */
20
+ function getQualityGatesStatus() {
21
+ const reportPath = path.join(process.cwd(), '.caws', 'quality-gates-report.json');
22
+
23
+ if (fs.existsSync(reportPath)) {
24
+ try {
25
+ const report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
26
+ return {
27
+ status: report.passed ? 'passing' : 'failing',
28
+ last_validated: report.timestamp || new Date().toISOString(),
29
+ violations: report.violations || 0,
30
+ gates: report.gates || {}
31
+ };
32
+ } catch (error) {
33
+ // Fall through to default
34
+ }
35
+ }
36
+
37
+ return {
38
+ status: 'not_validated',
39
+ last_validated: null,
40
+ violations: null
41
+ };
42
+ }
43
+
13
44
  /**
14
45
  * Provenance command handler
15
46
  * @param {string} subcommand - The subcommand to execute
@@ -87,12 +118,7 @@ async function updateProvenance(options) {
87
118
  mode: spec.mode,
88
119
  waiver_ids: spec.waiver_ids || [],
89
120
  },
90
- quality_gates: {
91
- // This would be populated by recent validation results
92
- // For now, we'll mark as unknown
93
- status: 'unknown',
94
- last_validated: new Date().toISOString(),
95
- },
121
+ quality_gates: getQualityGatesStatus(),
96
122
  agent: {
97
123
  type: detectAgentType(),
98
124
  confidence_level: null, // Would be populated by agent actions
@@ -407,6 +433,67 @@ function analyzeQualityMetrics(aiEntries) {
407
433
  /**
408
434
  * Analyze checkpoint usage patterns
409
435
  */
436
+ /**
437
+ * Calculate actual revert rate from git history
438
+ * Analyzes commits for revert patterns and calculates the percentage
439
+ * @param {number} maxCommits - Maximum number of commits to analyze
440
+ * @returns {number} Revert rate as a decimal (0.0 - 1.0)
441
+ */
442
+ function calculateRevertRate(maxCommits = 500) {
443
+ try {
444
+ // Get total commit count (limited)
445
+ const logOutput = execSync(`git log --oneline -n ${maxCommits} 2>/dev/null`, {
446
+ encoding: 'utf8',
447
+ cwd: process.cwd(),
448
+ }).trim();
449
+
450
+ if (!logOutput) {
451
+ return 0;
452
+ }
453
+
454
+ const totalCommits = logOutput.split('\n').filter(Boolean).length;
455
+
456
+ // Count revert commits (commits with "revert" in the message)
457
+ const revertOutput = execSync(
458
+ `git log --oneline -n ${maxCommits} --grep="[Rr]evert" 2>/dev/null || true`,
459
+ {
460
+ encoding: 'utf8',
461
+ cwd: process.cwd(),
462
+ }
463
+ ).trim();
464
+
465
+ const revertCommits = revertOutput ? revertOutput.split('\n').filter(Boolean).length : 0;
466
+
467
+ // Also check for reset/force-push patterns in reflog if available
468
+ let additionalReverts = 0;
469
+ try {
470
+ const reflogOutput = execSync(`git reflog --oneline -n ${maxCommits} 2>/dev/null || true`, {
471
+ encoding: 'utf8',
472
+ cwd: process.cwd(),
473
+ }).trim();
474
+
475
+ if (reflogOutput) {
476
+ const reflogLines = reflogOutput.split('\n').filter(Boolean);
477
+ additionalReverts = reflogLines.filter(
478
+ (line) => line.includes('reset:') || line.includes('checkout:')
479
+ ).length;
480
+ // Weight reflog reverts less since they may not be actual code reverts
481
+ additionalReverts = Math.floor(additionalReverts * 0.1);
482
+ }
483
+ } catch {
484
+ // Reflog not available or failed
485
+ }
486
+
487
+ const totalReverts = revertCommits + additionalReverts;
488
+ const revertRate = totalCommits > 0 ? totalReverts / totalCommits : 0;
489
+
490
+ return Math.min(1.0, revertRate); // Cap at 100%
491
+ } catch {
492
+ // Git not available or not a repo
493
+ return 0;
494
+ }
495
+ }
496
+
410
497
  function analyzeCheckpointUsage(aiEntries) {
411
498
  const entriesWithCheckpoints = aiEntries.filter(
412
499
  (entry) => entry.checkpoints?.available && entry.checkpoints.checkpoints?.length > 0
@@ -416,8 +503,8 @@ function analyzeCheckpointUsage(aiEntries) {
416
503
  .filter((entry) => entry.checkpoints?.available)
417
504
  .reduce((sum, entry) => sum + (entry.checkpoints.checkpoints?.length || 0), 0);
418
505
 
419
- // Mock revert rate - in real implementation, this would track actual reverts
420
- const revertRate = 0.15; // 15% estimated revert rate
506
+ // Calculate actual revert rate from git history
507
+ const revertRate = calculateRevertRate();
421
508
 
422
509
  return {
423
510
  entriesWithCheckpoints,
@@ -753,57 +840,63 @@ function provideAIInsights(contributionPatterns, qualityMetrics, checkpointAnaly
753
840
 
754
841
  /**
755
842
  * Get Cursor AI code tracking data for a commit
843
+ * Uses Cursor's AI Code Tracking API (Enterprise feature)
844
+ * @see https://cursor.com/docs/account/teams/ai-code-tracking-api
756
845
  * @param {string} commitHash - Git commit hash to analyze
757
846
  * @returns {Promise<Object>} AI code tracking data
758
847
  */
759
848
  async function getCursorTrackingData(commitHash) {
849
+ const apiUrl = process.env.CURSOR_TRACKING_API;
850
+ const apiKey = process.env.CURSOR_API_KEY;
851
+
852
+ if (!apiUrl || !apiKey) {
853
+ return {
854
+ available: false,
855
+ reason: 'Cursor API not configured. Set CURSOR_TRACKING_API and CURSOR_API_KEY environment variables.',
856
+ documentation: 'https://cursor.com/docs/account/teams/ai-code-tracking-api'
857
+ };
858
+ }
859
+
760
860
  try {
761
- // Check if Cursor tracking API is available
762
- if (!process.env.CURSOR_TRACKING_API || !process.env.CURSOR_PROJECT_ID) {
763
- return { available: false, reason: 'Cursor tracking API not configured' };
861
+ // Basic auth: base64(apiKey:) - Cursor API uses API key with empty password
862
+ const auth = Buffer.from(`${apiKey}:`).toString('base64');
863
+
864
+ const response = await fetch(`${apiUrl}/analytics/ai-code/commits`, {
865
+ method: 'GET',
866
+ headers: {
867
+ 'Authorization': `Basic ${auth}`,
868
+ 'Content-Type': 'application/json',
869
+ }
870
+ });
871
+
872
+ if (!response.ok) {
873
+ return {
874
+ available: false,
875
+ reason: `Cursor API error: ${response.status} ${response.statusText}`
876
+ };
764
877
  }
765
878
 
766
- // In a real implementation, this would call the Cursor API
767
- // For now, we'll return a mock structure showing what data would be available
768
- const mockTrackingData = {
879
+ const data = await response.json();
880
+
881
+ // Find commit-specific data if available
882
+ const commitData = data.commits?.find(c => c.commit_hash === commitHash) || data;
883
+
884
+ // Transform API response to our internal format
885
+ return {
769
886
  available: true,
770
887
  commit_hash: commitHash,
771
- ai_code_breakdown: {
772
- tab_completions: {
773
- lines_added: 45,
774
- percentage: 35,
775
- files_affected: ['src/utils.js', 'tests/utils.test.js'],
776
- },
777
- composer_chat: {
778
- lines_added: 78,
779
- percentage: 60,
780
- files_affected: ['src/new-feature.js', 'src/api.js'],
781
- checkpoints_created: 3,
782
- },
783
- manual_human: {
784
- lines_added: 5,
785
- percentage: 5,
786
- files_affected: ['README.md'],
787
- },
888
+ ai_code_breakdown: commitData.ai_code_breakdown || {
889
+ tab_completions: { lines_added: 0, percentage: 0, files_affected: [] },
890
+ composer_chat: { lines_added: 0, percentage: 0, files_affected: [], checkpoints_created: 0 },
891
+ manual_human: { lines_added: 0, percentage: 0, files_affected: [] },
788
892
  },
789
- change_groups: [
790
- {
791
- change_id: 'cg_12345',
792
- type: 'composer_session',
793
- lines_ai_generated: 42,
794
- lines_human_edited: 8,
795
- confidence_score: 0.85,
796
- timestamp: new Date().toISOString(),
797
- },
798
- ],
799
- quality_metrics: {
800
- ai_code_quality_score: 0.78,
801
- human_override_rate: 0.12,
802
- acceptance_rate: 0.94,
893
+ change_groups: commitData.change_groups || [],
894
+ quality_metrics: commitData.quality_metrics || {
895
+ ai_code_quality_score: 0,
896
+ human_override_rate: 0,
897
+ acceptance_rate: 0,
803
898
  },
804
899
  };
805
-
806
- return mockTrackingData;
807
900
  } catch (error) {
808
901
  return {
809
902
  available: false,
@@ -888,62 +981,92 @@ async function initProvenance(options) {
888
981
 
889
982
  /**
890
983
  * Get Cursor Composer/Chat checkpoint data
891
- * @returns {Promise<Array>} Array of checkpoint data
984
+ * Reads from local .cursor/ directory since checkpoints are stored locally by Cursor Agent
985
+ * @returns {Promise<Object>} Checkpoint data
892
986
  */
893
987
  async function getCursorCheckpoints() {
988
+ const cursorDir = path.join(process.cwd(), '.cursor');
989
+
990
+ if (!fs.existsSync(cursorDir)) {
991
+ return {
992
+ available: false,
993
+ reason: 'No .cursor directory found. Checkpoints are only available when using Cursor IDE.'
994
+ };
995
+ }
996
+
894
997
  try {
895
- // Check if Cursor checkpoint API is available
896
- if (!process.env.CURSOR_CHECKPOINT_API) {
897
- return { available: false, reason: 'Cursor checkpoint API not configured' };
998
+ // Look for checkpoint metadata in .cursor directory
999
+ // Cursor stores checkpoints locally during Composer/Agent sessions
1000
+ const checkpointPatterns = [
1001
+ '.cursor/**/checkpoint*.json',
1002
+ '.cursor/**/checkpoints.json',
1003
+ '.cursor/composer/checkpoints/*.json',
1004
+ '.cursor/agent/checkpoints/*.json',
1005
+ ];
1006
+
1007
+ let checkpointFiles = [];
1008
+ for (const pattern of checkpointPatterns) {
1009
+ const glob = require('glob');
1010
+ const matches = glob.sync(pattern, { cwd: process.cwd(), absolute: true });
1011
+ checkpointFiles = checkpointFiles.concat(matches);
898
1012
  }
899
1013
 
900
- // In a real implementation, this would call the Cursor checkpoint API
901
- // For now, we'll return a mock structure
902
- const mockCheckpoints = [
903
- {
904
- id: 'cp_001',
905
- timestamp: new Date(Date.now() - 3600000).toISOString(), // 1 hour ago
906
- description: 'Initial AI-generated function structure',
907
- changes_summary: {
908
- lines_added: 25,
909
- lines_modified: 0,
910
- files_affected: ['src/new-feature.js'],
911
- },
912
- ai_confidence: 0.82,
913
- can_revert: true,
914
- },
915
- {
916
- id: 'cp_002',
917
- timestamp: new Date(Date.now() - 1800000).toISOString(), // 30 min ago
918
- description: 'Added error handling and validation',
919
- changes_summary: {
920
- lines_added: 15,
921
- lines_modified: 8,
922
- files_affected: ['src/new-feature.js', 'tests/new-feature.test.js'],
923
- },
924
- ai_confidence: 0.91,
925
- can_revert: true,
926
- },
927
- {
928
- id: 'cp_003',
929
- timestamp: new Date().toISOString(), // Current
930
- description: 'Final implementation with documentation',
931
- changes_summary: {
932
- lines_added: 12,
933
- lines_modified: 5,
934
- files_affected: ['src/new-feature.js', 'README.md'],
935
- },
936
- ai_confidence: 0.88,
937
- can_revert: false, // Latest checkpoint
938
- },
939
- ];
1014
+ // Remove duplicates
1015
+ checkpointFiles = [...new Set(checkpointFiles)];
1016
+
1017
+ if (checkpointFiles.length === 0) {
1018
+ return {
1019
+ available: false,
1020
+ reason: 'No checkpoints found in current session. Checkpoints are created during Cursor Composer/Agent sessions.'
1021
+ };
1022
+ }
1023
+
1024
+ // Parse checkpoint files and aggregate data
1025
+ const checkpoints = [];
1026
+ for (const file of checkpointFiles) {
1027
+ try {
1028
+ const content = await fs.readFile(file, 'utf8');
1029
+ const data = JSON.parse(content);
1030
+
1031
+ // Handle both single checkpoint and array of checkpoints
1032
+ if (Array.isArray(data)) {
1033
+ checkpoints.push(...data);
1034
+ } else if (data.checkpoints) {
1035
+ checkpoints.push(...data.checkpoints);
1036
+ } else if (data.id || data.timestamp) {
1037
+ checkpoints.push(data);
1038
+ }
1039
+ } catch (parseError) {
1040
+ // Skip invalid checkpoint files
1041
+ continue;
1042
+ }
1043
+ }
1044
+
1045
+ if (checkpoints.length === 0) {
1046
+ return {
1047
+ available: false,
1048
+ reason: 'No valid checkpoints found in checkpoint files.'
1049
+ };
1050
+ }
1051
+
1052
+ // Sort by timestamp (newest first)
1053
+ checkpoints.sort((a, b) => {
1054
+ const timeA = new Date(a.timestamp || 0).getTime();
1055
+ const timeB = new Date(b.timestamp || 0).getTime();
1056
+ return timeB - timeA;
1057
+ });
1058
+
1059
+ // Mark latest checkpoint as non-revertible
1060
+ if (checkpoints.length > 0) {
1061
+ checkpoints[0].can_revert = false;
1062
+ }
940
1063
 
941
- return { available: true, checkpoints: mockCheckpoints };
1064
+ return { available: true, checkpoints };
942
1065
  } catch (error) {
943
1066
  return {
944
1067
  available: false,
945
1068
  error: error.message,
946
- reason: 'Failed to retrieve Cursor checkpoint data',
1069
+ reason: 'Failed to read Cursor checkpoint data',
947
1070
  };
948
1071
  }
949
1072
  }
@@ -1 +1 @@
1
- {"version":3,"file":"quality-gates.d.ts","sourceRoot":"","sources":["../../src/commands/quality-gates.js"],"names":[],"mappings":"AAqBA;;;GAGG;AACH,iEA4ZC"}
1
+ {"version":3,"file":"quality-gates.d.ts","sourceRoot":"","sources":["../../src/commands/quality-gates.js"],"names":[],"mappings":"AAqBA;;;GAGG;AACH,iEA8ZC"}
@@ -339,9 +339,11 @@ async function qualityGatesCommand(options = {}) {
339
339
  Output.info(`Command: ${args.join(' ')}`);
340
340
 
341
341
  // Execute the quality gates runner with timeout
342
+ // CRITICAL: Must run from projectRoot (user's current directory) so that
343
+ // git commands resolve correctly to the user's repository, not the CLI installation
342
344
  const child = spawn(args[0], args.slice(1), {
343
345
  stdio: 'inherit',
344
- cwd: packagesDir,
346
+ cwd: projectRoot,
345
347
  env: env,
346
348
  });
347
349
 
@@ -1 +1 @@
1
- {"version":3,"file":"specs.d.ts","sourceRoot":"","sources":["../../src/commands/specs.js"],"names":[],"mappings":"AAipBA;;;;GAIG;AACH,qCAHW,MAAM,+BA+LhB;AA3zBD;;;GAGG;AACH,qCAFa,OAAO,KAAQ,CAqB3B;AAED;;;;GAIG;AACH,kDAFa,OAAO,CAAC,IAAI,CAAC,CAMzB;AAED;;;GAGG;AACH,iCAFa,OAAO,OAAO,CAmC1B;AAED;;;;;GAKG;AACH,+BAJW,MAAM,kBAEJ,OAAO,KAAQ,CAkO3B;AAED;;;;GAIG;AACH,6BAHW,MAAM,GACJ,OAAO,CAAC,MAAO,IAAI,CAAC,CAiBhC;AAED;;;;;GAKG;AACH,+BAJW,MAAM,kBAEJ,OAAO,CAAC,OAAO,CAAC,CA6B5B;AAED;;;;GAIG;AACH,+BAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAmB5B;AAED;;;GAGG;AACH,sDA2CC;AAED;;;GAGG;AACH,oDAoCC;AAoHD;;;GAGG;AACH,yCAFa,OAAO,CAAC,MAAM,CAAC,CAqC3B;AA9nBD;;GAEG;AACH,wBAAkB,aAAa,CAAC;AAChC,6BAAuB,2BAA2B,CAAC"}
1
+ {"version":3,"file":"specs.d.ts","sourceRoot":"","sources":["../../src/commands/specs.js"],"names":[],"mappings":"AAm0BA;;;;GAIG;AACH,qCAHW,MAAM,+BA+LhB;AA7+BD;;;GAGG;AACH,qCAFa,OAAO,KAAQ,CAqB3B;AAED;;;;GAIG;AACH,kDAFa,OAAO,CAAC,IAAI,CAAC,CAMzB;AAED;;;GAGG;AACH,iCAFa,OAAO,OAAO,CAmC1B;AAED;;;;;GAKG;AACH,+BAJW,MAAM,kBAEJ,OAAO,KAAQ,CAkO3B;AAED;;;;GAIG;AACH,6BAHW,MAAM,GACJ,OAAO,CAAC,MAAO,IAAI,CAAC,CAiBhC;AAED;;;;;GAKG;AACH,+BAJW,MAAM,kBAEJ,OAAO,CAAC,OAAO,CAAC,CA6B5B;AAiID;;;;GAIG;AACH,+BAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAmB5B;AAED;;;GAGG;AACH,sDA2CC;AAED;;;GAGG;AACH,oDAoCC;AAuKD;;;GAGG;AACH,yCAFa,OAAO,CAAC,MAAM,CAAC,CAqC3B;AAhzBD;;GAEG;AACH,wBAAkB,aAAa,CAAC;AAChC,6BAAuB,2BAA2B,CAAC"}