@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 +0 -0
- package/commands/run.go +11 -12
- package/commands/sync.go +25 -7
- package/extractor/extractor.go +22 -17
- package/package.json +1 -1
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
|
|
60
|
-
|
|
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
|
-
|
|
68
|
-
break
|
|
67
|
+
filesToSync = append(filesToSync, file)
|
|
69
68
|
}
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
// Auto-sync
|
|
73
|
-
if
|
|
74
|
-
fmt.Printf("\nSyncing policies with LLM (processing %d
|
|
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(
|
|
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(
|
|
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
|
|
114
|
-
for _, file := range
|
|
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(
|
|
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
|
-
//
|
|
43
|
-
|
|
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(
|
|
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(
|
|
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
|
|
83
|
-
for _, file := range
|
|
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(
|
|
153
|
+
fmt.Printf("\n✓ Synced %d policies from %d changed file(s)\n", totalPolicies, len(filesToSync))
|
|
136
154
|
return nil
|
|
137
155
|
}
|
|
138
156
|
|
package/extractor/extractor.go
CHANGED
|
@@ -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
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
- Import/dependency
|
|
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
|
-
|
|
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
|