@tanagram/cli 0.1.9 → 0.1.11

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/bin/tanagram CHANGED
Binary file
package/commands/run.go CHANGED
@@ -56,22 +56,21 @@ func Run() error {
56
56
  return fmt.Errorf("failed to load cache: %w", err)
57
57
  }
58
58
 
59
- // Check each file for changes and auto-sync if needed
60
- needsSync := false
59
+ // Check each file for changes and collect which files need syncing
60
+ var filesToSync []string
61
61
  for _, file := range instructionFiles {
62
62
  changed, err := cache.HasChanged(file)
63
63
  if err != nil {
64
64
  return fmt.Errorf("failed to check if %s changed: %w", file, err)
65
65
  }
66
66
  if changed {
67
- needsSync = true
68
- break
67
+ filesToSync = append(filesToSync, file)
69
68
  }
70
69
  }
71
70
 
72
- // Auto-sync if any files changed
73
- if needsSync {
74
- fmt.Printf("\nSyncing policies with LLM (processing %d files in parallel)...\n", len(instructionFiles))
71
+ // Auto-sync only the files that changed
72
+ if len(filesToSync) > 0 {
73
+ fmt.Printf("\nSyncing policies with LLM (processing %d changed file(s) in parallel)...\n", len(filesToSync))
75
74
 
76
75
  ctx := context.Background()
77
76
 
@@ -84,7 +83,7 @@ func Run() error {
84
83
  }
85
84
 
86
85
  // Channel to collect results
87
- results := make(chan syncResult, len(instructionFiles))
86
+ results := make(chan syncResult, len(filesToSync))
88
87
  var wg sync.WaitGroup
89
88
 
90
89
  // Start spinner
@@ -103,15 +102,15 @@ func Run() error {
103
102
  mu.Lock()
104
103
  c := completed
105
104
  mu.Unlock()
106
- fmt.Printf("\r%s Processing files... (%d/%d completed)", chars[i%len(chars)], c, len(instructionFiles))
105
+ fmt.Printf("\r%s Processing files... (%d/%d completed)", chars[i%len(chars)], c, len(filesToSync))
107
106
  i++
108
107
  time.Sleep(100 * time.Millisecond)
109
108
  }
110
109
  }
111
110
  }()
112
111
 
113
- // Launch goroutines for each file
114
- for _, file := range instructionFiles {
112
+ // Launch goroutines only for changed files
113
+ for _, file := range filesToSync {
115
114
  wg.Add(1)
116
115
  go func(file string) {
117
116
  defer wg.Done()
@@ -162,7 +161,7 @@ func Run() error {
162
161
  return fmt.Errorf("failed to save cache: %w", err)
163
162
  }
164
163
 
165
- fmt.Printf("\n✓ Synced %d policies from %d file(s)\n", totalPolicies, len(instructionFiles))
164
+ fmt.Printf("\n✓ Synced %d policies from %d changed file(s)\n", totalPolicies, len(filesToSync))
166
165
  }
167
166
 
168
167
  // Load all policies from cache
package/commands/sync.go CHANGED
@@ -39,8 +39,26 @@ func Sync() error {
39
39
  return fmt.Errorf("failed to load cache: %w", err)
40
40
  }
41
41
 
42
- // Parse and sync each file using LLM in parallel
43
- fmt.Printf("\nSyncing policies with LLM (processing %d files in parallel)...\n", len(instructionFiles))
42
+ // Check which files have changed and need syncing
43
+ var filesToSync []string
44
+ for _, file := range instructionFiles {
45
+ changed, err := cache.HasChanged(file)
46
+ if err != nil {
47
+ return fmt.Errorf("failed to check if %s changed: %w", file, err)
48
+ }
49
+ if changed {
50
+ filesToSync = append(filesToSync, file)
51
+ }
52
+ }
53
+
54
+ // If no files changed, nothing to sync
55
+ if len(filesToSync) == 0 {
56
+ fmt.Println("✓ All instruction files are up to date")
57
+ return nil
58
+ }
59
+
60
+ // Parse and sync only changed files using LLM in parallel
61
+ fmt.Printf("\nSyncing policies with LLM (processing %d changed file(s) in parallel)...\n", len(filesToSync))
44
62
 
45
63
  ctx := context.Background()
46
64
 
@@ -53,7 +71,7 @@ func Sync() error {
53
71
  }
54
72
 
55
73
  // Channel to collect results
56
- results := make(chan syncResult, len(instructionFiles))
74
+ results := make(chan syncResult, len(filesToSync))
57
75
  var wg sync.WaitGroup
58
76
 
59
77
  // Start spinner
@@ -72,15 +90,15 @@ func Sync() error {
72
90
  mu.Lock()
73
91
  c := completed
74
92
  mu.Unlock()
75
- fmt.Printf("\r%s Processing files... (%d/%d completed)", chars[i%len(chars)], c, len(instructionFiles))
93
+ fmt.Printf("\r%s Processing files... (%d/%d completed)", chars[i%len(chars)], c, len(filesToSync))
76
94
  i++
77
95
  time.Sleep(100 * time.Millisecond)
78
96
  }
79
97
  }
80
98
  }()
81
99
 
82
- // Launch goroutines for each file
83
- for _, file := range instructionFiles {
100
+ // Launch goroutines only for changed files
101
+ for _, file := range filesToSync {
84
102
  wg.Add(1)
85
103
  go func(file string) {
86
104
  defer wg.Done()
@@ -132,7 +150,7 @@ func Sync() error {
132
150
  return fmt.Errorf("failed to save cache: %w", err)
133
151
  }
134
152
 
135
- fmt.Printf("\n✓ Synced %d policies from %d file(s)\n", totalPolicies, len(instructionFiles))
153
+ fmt.Printf("\n✓ Synced %d policies from %d changed file(s)\n", totalPolicies, len(filesToSync))
136
154
  return nil
137
155
  }
138
156
 
@@ -60,28 +60,33 @@ func ExtractPolicies(ctx context.Context, content string) ([]parser.Policy, erro
60
60
 
61
61
  // buildExtractionPrompt creates the prompt for policy extraction
62
62
  func buildExtractionPrompt(content string) string {
63
- return fmt.Sprintf(`You are a code policy extraction system. Extract ONLY coding policies that apply when developers write and edit code.
64
-
65
- Analyze the following instruction file and extract policies that define:
66
- - Code structure and organization rules
67
- - Coding standards and style guidelines
68
- - Language-specific patterns and practices
69
- - File naming and directory conventions
70
- - Error handling requirements
71
- - Security practices in code
72
- - Testing requirements
73
- - Performance optimization rules
74
- - Import/dependency management
75
-
76
- DO NOT extract:
63
+ return fmt.Sprintf(`You are a code policy extraction system. Extract ONLY policies that define anti-patterns or bad practices that can be detected by reading code.
64
+
65
+ IMPORTANT: Extract policies about what the CODE should or shouldn't look like. DO NOT extract policies that require running commands, executing tools, or performing actions.
66
+
67
+ Extract policies that define CODE ANTI-PATTERNS:
68
+ - Code structure and organization anti-patterns (e.g., "Don't use deeply nested functions")
69
+ - Coding standards violations (e.g., "Don't use var, use let/const")
70
+ - Language-specific anti-patterns (e.g., "Don't use 'any' type in TypeScript")
71
+ - Prohibited code patterns (e.g., "Don't hardcode API keys")
72
+ - Security anti-patterns in code (e.g., "Don't use eval()")
73
+ - Error handling anti-patterns (e.g., "Don't swallow exceptions silently")
74
+ - Import/dependency anti-patterns (e.g., "Don't import entire lodash library")
75
+
76
+ DO NOT extract policies that require ACTIONS or COMMANDS:
77
+ - Running tests (e.g., "Run pytest before committing")
78
+ - Running linters or formatters (e.g., "Run black on all Python files")
79
+ - Building or compiling (e.g., "Build the project to verify")
80
+ - Running scripts or commands (e.g., "Execute database migrations")
81
+ - Using specific tools (e.g., "Use ruff format" - this requires running ruff)
77
82
  - Agent behavior instructions (how AI agents should operate)
78
83
  - Workflow or process instructions
79
- - Tool usage instructions
80
84
  - Communication style guidelines
81
85
  - Project management policies
82
- - Non-code related guidelines
83
86
 
84
- For each code policy, provide:
87
+ CRITICAL: If a policy would require the agent to run a command or tool to fix a violation, DO NOT extract it. Only extract policies about code patterns that can be fixed by editing code directly.
88
+
89
+ For each code anti-pattern policy, provide:
85
90
  1. Name: Short descriptive name (2-5 words)
86
91
  2. Message: The full policy text or a clear summary
87
92
  3. OriginalText: The exact text from the file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanagram/cli",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Tanagram - Catch sloppy code before it ships",
5
5
  "main": "index.js",
6
6
  "bin": {