Go · 47648 bytes Raw Blame History
1 package llm
2
3 import (
4 "os"
5 "path/filepath"
6 "regexp"
7 "strconv"
8 "strings"
9 "time"
10 )
11
12 // SmartFallbackContext contains all context needed for intelligent fallback generation
13 type SmartFallbackContext struct {
14 Command string
15 CommandType string
16 Subcommand string
17 Arguments []string
18 ExitCode int
19 FullCommand string
20
21 // Tier 1 Intelligence
22 Environment map[string]string
23 WorkingDir string
24 TimeOfDay int // Hour 0-23
25 FileExtensions []string
26 CommandLength int
27 NumericArgs []int
28 Shell string
29 HasPipes bool
30 HasChaining bool
31
32 // Tier 2 Intelligence
33 GitBranch string
34 ProjectType string // "node", "rust", "go", "python", "java", etc.
35 ProjectFiles []string // List of project files found
36
37 // Tier 3 Intelligence
38 IsCI bool // Running in CI/CD environment
39 CIProvider string // "github", "gitlab", "jenkins", "circle", etc.
40 HasDockerfile bool
41 HasMakefile bool
42 DependencyCount int // Rough estimate of dependencies
43 ErrorPattern string // Detected error pattern
44 IsRepeatedFailure bool // Same command failed recently
45 }
46
47 // ParseCommandContext extracts context from a command for intelligent fallback
48 func ParseCommandContext(command string, commandType string, exitCode string) SmartFallbackContext {
49 ctx := SmartFallbackContext{
50 FullCommand: command,
51 CommandType: commandType,
52 Environment: make(map[string]string),
53 }
54
55 // Parse exit code
56 if ec, err := strconv.Atoi(exitCode); err == nil {
57 ctx.ExitCode = ec
58 }
59
60 // Parse command into parts
61 parts := strings.Fields(command)
62 if len(parts) == 0 {
63 return ctx
64 }
65
66 ctx.Command = parts[0]
67 if len(parts) > 1 {
68 ctx.Subcommand = parts[1]
69 ctx.Arguments = parts[2:]
70 }
71
72 // Tier 1 Intelligence Gathering
73 ctx.CommandLength = len(command)
74 ctx.TimeOfDay = time.Now().Hour()
75 ctx.HasPipes = strings.Contains(command, "|")
76 ctx.HasChaining = strings.Contains(command, "&&") || strings.Contains(command, "||")
77
78 // Get working directory
79 if wd, err := os.Getwd(); err == nil {
80 ctx.WorkingDir = wd
81 }
82
83 // Get shell type
84 ctx.Shell = filepath.Base(os.Getenv("SHELL"))
85
86 // Collect interesting environment variables
87 envVars := []string{"CI", "DEBUG", "NODE_ENV", "PROD", "PRODUCTION", "STAGING", "DEVELOPMENT",
88 "GITHUB_ACTIONS", "GITLAB_CI", "JENKINS_HOME", "CIRCLECI", "TRAVIS"}
89 for _, envVar := range envVars {
90 if val := os.Getenv(envVar); val != "" {
91 ctx.Environment[envVar] = val
92 }
93 }
94
95 // Extract file extensions from command
96 extRegex := regexp.MustCompile(`\.\w{1,6}\b`)
97 exts := extRegex.FindAllString(command, -1)
98 ctx.FileExtensions = exts
99
100 // Extract numeric arguments (ports, chmod values, PIDs, etc.)
101 numRegex := regexp.MustCompile(`\b\d+\b`)
102 nums := numRegex.FindAllString(command, -1)
103 for _, num := range nums {
104 if n, err := strconv.Atoi(num); err == nil {
105 ctx.NumericArgs = append(ctx.NumericArgs, n)
106 }
107 }
108
109 // Tier 2 Intelligence Gathering
110
111 // Detect git branch if in a git repo
112 ctx.GitBranch = detectGitBranch()
113
114 // Detect project type by checking for common project files
115 ctx.ProjectType, ctx.ProjectFiles = detectProjectType()
116
117 // Tier 3 Intelligence Gathering
118
119 // Detect CI/CD environment
120 ctx.IsCI, ctx.CIProvider = detectCIEnvironment(ctx.Environment)
121
122 // Detect Docker and build files
123 ctx.HasDockerfile = fileExists("Dockerfile") || fileExists("docker-compose.yml")
124 ctx.HasMakefile = fileExists("Makefile")
125
126 // Estimate dependency count
127 ctx.DependencyCount = estimateDependencyCount(ctx.ProjectType)
128
129 // Detect common error patterns from exit code
130 ctx.ErrorPattern = detectErrorPattern(ctx.ExitCode, command)
131
132 // Track repeated failures (simple in-process tracking)
133 ctx.IsRepeatedFailure = trackFailure(command)
134
135 return ctx
136 }
137
138 // Global insult scorer and database (initialized once)
139 var (
140 insultDB *InsultDatabase
141 insultScorer *InsultScorer
142 insultHist *InsultHistory
143 ensembleSystem *EnsembleSystem
144 )
145
146 func init() {
147 // Initialize ML-inspired components on first use
148 insultDB = NewInsultDatabase()
149 insultScorer = NewInsultScorer(insultDB)
150 insultHist = NewInsultHistory(20) // Track last 20 insults
151
152 // Initialize the ensemble system (combines TF-IDF, Markov, and tag-based scoring)
153 ensembleSystem = NewEnsembleSystem(insultDB, insultScorer, insultHist)
154
155 // Train the ensemble system on startup (async to avoid blocking)
156 go ensembleSystem.Train()
157 }
158
159 // GenerateSmartFallback generates a context-aware insult
160 func GenerateSmartFallback(ctx SmartFallbackContext) string {
161 // Load user history for Tier 4 intelligence
162 history := LoadUserHistory()
163
164 // Record this failure
165 if history != nil {
166 history.RecordFailure(ctx)
167 }
168
169 // TIER 5 INTELLIGENCE - ML-Inspired Semantic Matching (HIGHEST PRIORITY)
170 // Uses error classification, intent parsing, and multi-factor scoring
171 if insult := generateMLInsult(ctx); insult != "" {
172 return insult
173 }
174
175 // TIER 4 INTELLIGENCE - Historical Learning & Dynamic Generation
176
177 // 1. Failure streak escalation (gets more brutal over time)
178 if history != nil && history.CurrentStreak >= 2 {
179 if insult := GenerateStreakEscalation(history.CurrentStreak, ctx); insult != "" {
180 return insult
181 }
182 }
183
184 // 2. Historical pattern-based insults (learns from past failures)
185 if history != nil && history.TotalFailures > 0 {
186 if insult := GenerateHistoricalInsult(history, ctx); insult != "" {
187 return insult
188 }
189 }
190
191 // 3. Dynamic template-based generation (infinite combinations)
192 if insult := GenerateDynamicInsult(ctx, history); insult != "" {
193 return insult
194 }
195
196 // 4. Savage mode (brutal, devastating insults)
197 // Activate savage mode for: high streaks, high total failures, or specific contexts
198 if history != nil && (history.CurrentStreak >= 5 || history.TotalFailures >= 50) {
199 if insult := GetAnySavageInsult(ctx.FullCommand); insult != "" {
200 return insult
201 }
202 }
203
204 // Tier 3 Intelligence - LLM-like awareness
205
206 // 5. Repeated failure escalation
207 if insult := getRepeatedFailureInsult(ctx); insult != "" {
208 return insult
209 }
210
211 // 6. CI/CD environment detection
212 if insult := getCIInsult(ctx); insult != "" {
213 return insult
214 }
215
216 // 7. Error pattern recognition
217 if insult := getErrorPatternInsult(ctx); insult != "" {
218 return insult
219 }
220
221 // 8. Docker/Build system awareness
222 if insult := getBuildSystemInsult(ctx); insult != "" {
223 return insult
224 }
225
226 // 9. Dependency complexity awareness
227 if insult := getDependencyInsult(ctx); insult != "" {
228 return insult
229 }
230
231 // Tier 2 Intelligence
232
233 // 6. Git branch awareness
234 if insult := getGitBranchInsult(ctx); insult != "" {
235 return insult
236 }
237
238 // 7. Project type detection
239 if insult := getProjectTypeInsult(ctx); insult != "" {
240 return insult
241 }
242
243 // Tier 1 Intelligence - Priority Order
244
245 // 3. Environment-specific insults
246 if insult := getEnvironmentInsult(ctx); insult != "" {
247 return insult
248 }
249
250 // 2. Time-sensitive insults
251 if insult := getTimeOfDayInsult(ctx); insult != "" {
252 return insult
253 }
254
255 // 3. Working directory insults
256 if insult := getWorkingDirInsult(ctx); insult != "" {
257 return insult
258 }
259
260 // 4. File extension insults
261 if insult := getFileExtensionInsult(ctx); insult != "" {
262 return insult
263 }
264
265 // 5. Numeric argument insults
266 if insult := getNumericArgumentInsult(ctx); insult != "" {
267 return insult
268 }
269
270 // 6. Shell-specific insults
271 if insult := getShellInsult(ctx); insult != "" {
272 return insult
273 }
274
275 // 7. Command complexity insults
276 if insult := getCommandComplexityInsult(ctx); insult != "" {
277 return insult
278 }
279
280 // Existing intelligence layers
281
282 // 8. Exit code specific insults
283 if insult := getExitCodeInsult(ctx); insult != "" {
284 return insult
285 }
286
287 // 9. Command-specific patterns
288 if insult := getCommandPatternInsult(ctx); insult != "" {
289 return insult
290 }
291
292 // 10. Argument-aware insults
293 if insult := getArgumentAwareInsult(ctx); insult != "" {
294 return insult
295 }
296
297 // 11. Fall back to expanded database
298 return GetExpandedFallback(ctx.CommandType, ctx.FullCommand)
299 }
300
301 // getExitCodeInsult returns insults specific to common exit codes
302 func getExitCodeInsult(ctx SmartFallbackContext) string {
303 exitCodeInsults := map[int][]string{
304 1: {
305 "Exit code 1: One failure, infinite disappointment.",
306 "Generic error for a generic developer.",
307 "Exit 1: First step to unemployment.",
308 "Error level 1: Your competence level 0.",
309 "Failed with distinction: Exit code 1.",
310 },
311 2: {
312 "Exit 2: Misuse of command. Misuse of developer title.",
313 "Built-in syntax error: You're a built-in failure.",
314 "Wrong arguments. Wrong career.",
315 "Command misuse detected. Life misuse detected.",
316 "Exit 2: Two brain cells, neither working.",
317 },
318 126: {
319 "Permission denied: Can't execute what you wrote anyway.",
320 "Not executable: Neither are your plans.",
321 "126: Command found, competence not found.",
322 "Can't execute: Your logic isn't executable either.",
323 },
324 127: {
325 "Command not found: Neither is your skill.",
326 "127: Path to success not found.",
327 "Command doesn't exist. Your competence doesn't exist.",
328 "Not in PATH: You're not on the path to success.",
329 "Command not found: Story of your career.",
330 },
331 128: {
332 "Invalid exit argument. Invalid life argument.",
333 "Exit 128: One-two-eight steps to failure.",
334 "Invalid signal: Your brain sends invalid signals.",
335 },
336 130: {
337 "Ctrl+C? Can't escape your mistakes that easily.",
338 "Interrupted: Like your thought process.",
339 "SIGINT: Significance? Interrupted.",
340 "Killed by keyboard: At least something stopped you.",
341 },
342 137: {
343 "SIGKILL: Something had to stop you forcefully.",
344 "Exit 137: Murdered by the system. Deservedly.",
345 "Killed with prejudice: OOMKiller knows best.",
346 "137: You were killed. Your code was mercy-killed.",
347 },
348 139: {
349 "Segmentation fault: Your logic segfaulted first.",
350 "139: Memory violation. Logic violation. Everything violation.",
351 "Segfault: Your brain segfaulted at compile time.",
352 "Core dumped: Your core competencies dumped earlier.",
353 },
354 143: {
355 "SIGTERM: Terminated for being terrible.",
356 "Graceful termination: More graceful than your code.",
357 "143: Terminated by common sense.",
358 },
359 255: {
360 "Exit 255: Overflow of failure.",
361 "Maximum exit code: Maximum incompetence.",
362 "255: You maxed out the failure counter.",
363 "Exit code overflow: Like your error overflow.",
364 },
365 }
366
367 if insults, exists := exitCodeInsults[ctx.ExitCode]; exists {
368 return selectInsult(insults, ctx.FullCommand)
369 }
370
371 return ""
372 }
373
374 // getCommandPatternInsult returns insults based on command + subcommand patterns
375 func getCommandPatternInsult(ctx SmartFallbackContext) string {
376 pattern := ctx.Command + " " + ctx.Subcommand
377 pattern = strings.TrimSpace(pattern)
378
379 commandPatterns := map[string][]string{
380 // Git operations
381 "git push": {
382 "Push rejected: The remote has standards.",
383 "Git push failed: Even version control rejects you.",
384 "Rejected by remote: Story of your life.",
385 "Push denied: Your code is unpushable.",
386 "Remote said no: Listen to the remote.",
387 "Can't push incompetence to production.",
388 "Git push failed: Your career trajectory in command form.",
389 },
390 "git pull": {
391 "Pull failed: Can't pull competence from thin air.",
392 "Merge conflicts incoming: Your code vs. reality.",
393 "Pull rejected: Your branch diverged from sanity.",
394 "Can't pull: You're already pulling everyone down.",
395 "Fetch failed: Can't fetch what doesn't exist.",
396 },
397 "git commit": {
398 "Commit failed: Even git won't commit to your code.",
399 "Nothing to commit: Nothing worth committing.",
400 "Pre-commit hook failed: Your code failed harder.",
401 "Can't commit disaster: Wait, git tried and failed.",
402 "Commit message empty: Like your understanding.",
403 },
404 "git merge": {
405 "Merge failed: Can't merge competence into chaos.",
406 "Conflict resolution required: Start with your career.",
407 "Merge aborted: Smart choice by git.",
408 "Auto-merge failed: Manual merge won't help you either.",
409 },
410 "git clone": {
411 "Clone failed: Repository running away from you.",
412 "Can't clone competence: It doesn't exist to clone.",
413 "Permission denied: Even public repos protect themselves.",
414 "Clone timeout: Repository chose death over your attention.",
415 },
416 "git rebase": {
417 "Rebase failed: Can't rebase on a foundation of failure.",
418 "Interactive rebase: Interactively watching you fail.",
419 "Rebase conflict: Your existence conflicts with success.",
420 "Can't rewrite history to hide your incompetence.",
421 },
422 "git checkout": {
423 "Checkout failed: Can't check out from reality.",
424 "Branch not found: Neither is your competence.",
425 "Detached HEAD: Matches your detachment from reality.",
426 "Already on that branch: Already on the failure branch.",
427 },
428 "git reset": {
429 "Reset failed: Can't reset your mistakes that easily.",
430 "Hard reset won't fix soft skills.",
431 "Resetting to a previous commit won't fix current you.",
432 },
433 "git stash": {
434 "Stash failed: Can't stash your incompetence away.",
435 "Nothing to stash: Nothing worth saving.",
436 "Stash apply failed: Your problems can't be applied away.",
437 },
438 "git branch": {
439 "Branch creation failed: Branching into more failure.",
440 "Can't create branch: Too many failure branches already.",
441 "Branch diverged: You diverged from competence long ago.",
442 },
443 "git fetch": {
444 "Fetch failed: Can't fetch common sense.",
445 "Nothing to fetch: Nothing to learn from you either.",
446 "Remote unreachable: Like your career goals.",
447 },
448
449 // Docker operations
450 "docker build": {
451 "Build failed: Can't dockerize disaster.",
452 "Dockerfile syntax error: Your syntax is always wrong.",
453 "Build context too large: Your mistakes are infinite.",
454 "Layer failed: All your layers are failures.",
455 "FROM scratch: You are scratch.",
456 "Build arg undefined: Like your competence.",
457 },
458 "docker run": {
459 "Container exited immediately: Smart container.",
460 "Run failed: Nothing wants to run for you.",
461 "Port binding failed: Can't bind success to you.",
462 "Volume mount error: Can't mount your chaos.",
463 "Container crashed on startup: Your code in container form.",
464 },
465 "docker push": {
466 "Push denied: Registry has standards.",
467 "Authentication failed: You're not authenticated as competent.",
468 "Image push rejected: Your image is not production-ready.",
469 "Manifest invalid: Your competence manifest is invalid.",
470 },
471 "docker pull": {
472 "Pull failed: Can't pull what doesn't work.",
473 "Image not found: Your skill image doesn't exist.",
474 "Digest invalid: Can't digest your code.",
475 },
476 "docker-compose up": {
477 "Compose failed: Can't compose order from chaos.",
478 "Service unhealthy: You're the unhealthy service.",
479 "Network creation failed: Your networking is broken too.",
480 "Volume error: Can't volume-ize your mistakes.",
481 },
482 "docker exec": {
483 "Exec failed: Can't exec into disaster.",
484 "Container not running: Your competence isn't running either.",
485 "No such container: No such developer.",
486 },
487
488 // NPM operations
489 "npm install": {
490 "Install failed: NPM refuses to install for you.",
491 "Dependency hell: You're the dependency from hell.",
492 "Package not found: Neither is your talent.",
493 "ERESOLVE: Can't resolve your incompetence.",
494 "Peer dependency conflict: Your existence is a conflict.",
495 "Funding request: Fund your education first.",
496 },
497 "npm start": {
498 "Start script failed: Can't start what's broken.",
499 "Port already in use: By someone competent.",
500 "Module not found: Neither is your ability.",
501 },
502 "npm run": {
503 "Script not found: Neither is your skill.",
504 "Build failed: Can't build on a foundation of failure.",
505 "Test failed: Your code is the test, reality failed you.",
506 },
507 "npm test": {
508 "Tests failed: 0% passing, 100% crying.",
509 "Test suite disaster: Every assertion asserts your failure.",
510 "Coverage 0%: Covered in incompetence though.",
511 },
512
513 // Python operations
514 "python": {
515 "Python execution failed: The snake bit back.",
516 "ModuleNotFoundError: Module 'brain' not found.",
517 "SyntaxError: Invalid syntax, invalid developer.",
518 "IndentationError: Your career is misaligned too.",
519 },
520 "pip install": {
521 "Pip install failed: Package manager managing disappointment.",
522 "Requirements not met: Competence requirement not met.",
523 "Dependency resolution impossible: Like resolving to make you competent.",
524 },
525
526 // Rust operations
527 "cargo build": {
528 "Build failed: Rust compiles. You don't.",
529 "Borrow checker says no: You can't borrow competence.",
530 "Lifetime error: Your career lifetime is expiring.",
531 "Type mismatch: Expected developer, found disaster.",
532 },
533 "cargo run": {
534 "Run failed: Panic in main thread.",
535 "Binary execution failed: Your execution is always flawed.",
536 },
537
538 // Database operations
539 "mysql": {
540 "MySQL error: My SQL, your hell.",
541 "Connection refused: Database has self-respect.",
542 "Access denied: Denied access to success.",
543 },
544 "psql": {
545 "Postgres error: Post-gres, pre-disaster.",
546 "Connection failed: Can't connect competence to you.",
547 },
548
549 // Make/Build operations
550 "make": {
551 "Make failed: Make better choices.",
552 "Target not found: Your target of competence not found.",
553 "Recipe failed: Recipe for disaster succeeded though.",
554 },
555 "cmake": {
556 "CMake error: Can't make sense of you.",
557 "Configuration failed: You're misconfigured.",
558 },
559
560 // SSH operations
561 "ssh": {
562 "Connection refused: Server protecting itself.",
563 "Permission denied: Your credentials are insufficient.",
564 "Host key verification failed: Host doesn't trust you.",
565 "Timeout: Server chose silence over your presence.",
566 },
567 }
568
569 if insults, exists := commandPatterns[pattern]; exists {
570 return selectInsult(insults, ctx.FullCommand)
571 }
572
573 // Try just the command without subcommand
574 if insults, exists := commandPatterns[ctx.Command]; exists {
575 return selectInsult(insults, ctx.FullCommand)
576 }
577
578 return ""
579 }
580
581 // getArgumentAwareInsult returns insults based on command arguments
582 func getArgumentAwareInsult(ctx SmartFallbackContext) string {
583 // Check for specific argument patterns
584 fullCmd := strings.ToLower(ctx.FullCommand)
585
586 // Force operations
587 if strings.Contains(fullCmd, " -f") || strings.Contains(fullCmd, "--force") {
588 return selectInsult([]string{
589 "Force flag detected: Forcing failure down everyone's throat.",
590 "--force won't force competence into you.",
591 "Force push to production: Force push to unemployment.",
592 "Forcing it won't make it work. Like your career.",
593 }, ctx.FullCommand)
594 }
595
596 // Sudo operations
597 if strings.HasPrefix(fullCmd, "sudo") {
598 return selectInsult([]string{
599 "Sudo failed: Superuser can't grant super-competence.",
600 "Even root privileges can't fix your code.",
601 "Sudo make me a developer: Permission denied.",
602 "With great power comes great responsibility. You have neither.",
603 }, ctx.FullCommand)
604 }
605
606 // Recursive operations
607 if strings.Contains(fullCmd, " -r") || strings.Contains(fullCmd, "--recursive") {
608 return selectInsult([]string{
609 "Recursive fail: Failing recursively at every level.",
610 "-r flag: Recursively destroying everything.",
611 "Recursion depth exceeded: By your incompetence.",
612 }, ctx.FullCommand)
613 }
614
615 // Verbose operations
616 if strings.Contains(fullCmd, " -v") || strings.Contains(fullCmd, "--verbose") {
617 return selectInsult([]string{
618 "Verbose mode: More output, same failure.",
619 "--verbose showing verbose failure details.",
620 "Verbose mode: Because watching you fail in detail is entertaining.",
621 }, ctx.FullCommand)
622 }
623
624 // Help flags
625 if strings.Contains(fullCmd, " --help") || strings.Contains(fullCmd, " -h") {
626 return selectInsult([]string{
627 "Reading help? That ship sailed long ago.",
628 "--help can't help you now.",
629 "Even the help documentation gave up on you.",
630 "RTFM: Read The Failed Manual you just failed.",
631 }, ctx.FullCommand)
632 }
633
634 // Version checks
635 if strings.Contains(fullCmd, "--version") || strings.Contains(fullCmd, "-v") {
636 return selectInsult([]string{
637 "Checking version: Your version is deprecated.",
638 "--version: v0.0.0-incompetent",
639 "Software version: Current. Developer version: Obsolete.",
640 }, ctx.FullCommand)
641 }
642
643 return ""
644 }
645
646 // Tier 1 Intelligence Detection Functions
647
648 // getEnvironmentInsult returns insults based on environment variables
649 func getEnvironmentInsult(ctx SmartFallbackContext) string {
650 envInsults := map[string][]string{
651 "CI": {
652 "Breaking CI? Breaking everyone's day.",
653 "CI failure: Continuous Incompetence detected.",
654 "Failed in CI: Failing Continuously and Immediately.",
655 "CI pipeline broken: Your career pipeline next.",
656 },
657 "GITHUB_ACTIONS": {
658 "GitHub Actions failed: Your actions speak louder than words.",
659 "Actions workflow broken: Action item: Find new career.",
660 "GitHub runner quit: Running from your code.",
661 },
662 "GITLAB_CI": {
663 "GitLab CI failed: Lab results show terminal incompetence.",
664 "Pipeline failed: Pipe down, you're done.",
665 },
666 "JENKINS_HOME": {
667 "Jenkins build failed: Job security failed too.",
668 "Jenkins says no: Automated rejection system working.",
669 },
670 "DEBUG": {
671 "Debug mode active: Can't debug your brain.",
672 "Debugging? You ARE the bug.",
673 },
674 "PRODUCTION": {
675 "Production error: Producing only failures.",
676 "PROD failure: Professional Regression Of Development.",
677 "Testing in production? Testing everyone's patience.",
678 },
679 "NODE_ENV": {
680 "Node environment error: Environment of incompetence.",
681 },
682 }
683
684 for env, val := range ctx.Environment {
685 if insults, exists := envInsults[env]; exists && val != "" {
686 return selectInsult(insults, ctx.FullCommand)
687 }
688 }
689
690 return ""
691 }
692
693 // getTimeOfDayInsult returns insults based on time of day
694 func getTimeOfDayInsult(ctx SmartFallbackContext) string {
695 hour := ctx.TimeOfDay
696
697 switch {
698 case hour >= 0 && hour < 6:
699 return selectInsult([]string{
700 "3 AM debugging? Tomorrow won't fix today's code.",
701 "Coding at 3 AM? Your code is as tired as you.",
702 "Late night failure: Sleep won't fix this.",
703 "Midnight coding: Both your code and judgment are impaired.",
704 }, ctx.FullCommand)
705 case hour >= 6 && hour < 9:
706 return selectInsult([]string{
707 "Morning failure sets the tone for the day.",
708 "Failed before breakfast: Hungry for failure.",
709 "Early bird gets the worm: Early coder gets the bugs.",
710 }, ctx.FullCommand)
711 case hour >= 17 && hour < 20:
712 return selectInsult([]string{
713 "Evening failure: Overtime making more bugs.",
714 "5 PM deploy failed: Weekend ruined.",
715 "After hours coding: After competence hours too.",
716 }, ctx.FullCommand)
717 case hour >= 20 && hour < 24:
718 return selectInsult([]string{
719 "Late night commit: Commit to quitting instead.",
720 "Coding past 8 PM? Desperation detected.",
721 "Night owl? More like night fail.",
722 }, ctx.FullCommand)
723 }
724
725 return ""
726 }
727
728 // getWorkingDirInsult returns insults based on working directory
729 func getWorkingDirInsult(ctx SmartFallbackContext) string {
730 wd := strings.ToLower(ctx.WorkingDir)
731
732 dirPatterns := map[string][]string{
733 "/tmp": {
734 "Coding in /tmp? That's where your code belongs: temporary.",
735 "Temp directory for temp solution for temp developer.",
736 "/tmp: Temporary directory, permanent failure.",
737 },
738 "downloads": {
739 "Coding in Downloads? Your career is downloading too.",
740 "Downloads folder: Downloaded failure.",
741 },
742 "/var/log": {
743 "Working in logs? You belong in error logs.",
744 "/var/log: Logging your mistakes for posterity.",
745 },
746 "/root": {
747 "Running as root? Root of all problems.",
748 "Root directory? Rooted in incompetence.",
749 },
750 "desktop": {
751 "Desktop coding? Desktop disaster.",
752 "Desktop folder: Where careers go to die.",
753 },
754 "/opt": {
755 "Optional directory for optional competence.",
756 "/opt: Opted out of skill.",
757 },
758 }
759
760 for pattern, insults := range dirPatterns {
761 if strings.Contains(wd, pattern) {
762 return selectInsult(insults, ctx.FullCommand)
763 }
764 }
765
766 return ""
767 }
768
769 // getFileExtensionInsult returns insults based on file extensions in command
770 func getFileExtensionInsult(ctx SmartFallbackContext) string {
771 if len(ctx.FileExtensions) == 0 {
772 return ""
773 }
774
775 ext := strings.ToLower(ctx.FileExtensions[0])
776
777 extInsults := map[string][]string{
778 ".rs": {
779 "Rust file failed: Rust in peace, code.",
780 ".rs: Rust? Your skills are corroded.",
781 "Rust compile failed: Oxidized incompetence.",
782 },
783 ".go": {
784 "Go file failed: Stop. Don't go. Just don't.",
785 ".go error: Should've Go-ne into another career.",
786 "Go build failed: Go away.",
787 },
788 ".java": {
789 "Java failed: Needs more than coffee beans.",
790 ".java compile error: Java the Hutt-level bloat.",
791 "Java exception: You're the exception to competence.",
792 },
793 ".cpp": {
794 "C++ failed: C++ you later, career.",
795 ".cpp segfault: C++ more like C-- --.",
796 "C++ error: Can't ++ your skill level.",
797 },
798 ".c": {
799 "C compilation failed: C you don't understand C.",
800 ".c file error: C-riously incompetent.",
801 },
802 ".py": {
803 "Python failed: Snake bit back.",
804 ".py error: Python crying from your code.",
805 "Python IndentationError: Career misaligned too.",
806 },
807 ".js": {
808 "JavaScript failed: Just awful Script.",
809 ".js error: Java-Script? Neither Java nor scripted competence.",
810 },
811 ".ts": {
812 "TypeScript failed: Type: Disaster.",
813 ".ts error: TypeScript can't type your chaos.",
814 },
815 ".sh": {
816 "Shell script failed: Script kiddie confirmed.",
817 ".sh error: Shell-shocked by incompetence.",
818 },
819 ".rb": {
820 "Ruby failed: More like Rub-y wounds in codebase.",
821 ".rb error: Ruby gem? Cubic zirconia skill.",
822 },
823 ".php": {
824 "PHP failed: Probably Horrible Programming.",
825 ".php error: PHP stands for Please Help Professional.",
826 },
827 }
828
829 if insults, exists := extInsults[ext]; exists {
830 return selectInsult(insults, ctx.FullCommand)
831 }
832
833 return ""
834 }
835
836 // getNumericArgumentInsult returns insults based on numeric arguments
837 func getNumericArgumentInsult(ctx SmartFallbackContext) string {
838 if len(ctx.NumericArgs) == 0 {
839 return ""
840 }
841
842 num := ctx.NumericArgs[0]
843
844 // Port numbers
845 if num >= 1 && num <= 65535 {
846 portInsults := map[int][]string{
847 22: {
848 "Port 22: 22 ways to fail at SSH.",
849 "SSH on port 22: Access denied to competence.",
850 },
851 80: {
852 "Port 80: HTTP status 500 Internal User Error.",
853 "Port 80: Gateway to failure.",
854 },
855 443: {
856 "Port 443: HTTPS - Hyper Text Tragic Protocol Stupidity.",
857 "Port 443: Secure connection to incompetence.",
858 },
859 3000: {
860 "Port 3000: Three thousand problems detected.",
861 "Port 3000: Development port for underdeveloped skills.",
862 },
863 8080: {
864 "Port 8080: Eight-zero-eight-zero errors found.",
865 "Port 8080: Alternative HTTP, alternative competence (zero).",
866 },
867 5432: {
868 "Port 5432: PostgreSQL rejecting your queries and you.",
869 "Port 5432: Postgres? More like Post-regrets.",
870 },
871 3306: {
872 "Port 3306: MySQL - My Structured Query: Why are you coding?",
873 "Port 3306: MySQL rejecting your SQL and existence.",
874 },
875 27017: {
876 "Port 27017: MongoDB - More like MongoDON'T.",
877 "Port 27017: NoSQL? No skill either.",
878 },
879 }
880
881 if insults, exists := portInsults[num]; exists {
882 return selectInsult(insults, ctx.FullCommand)
883 }
884 }
885
886 // Chmod values
887 if num == 777 {
888 return selectInsult([]string{
889 "chmod 777: Maximum permissions, minimum security, zero brains.",
890 "777: Jackpot of incompetence.",
891 "chmod 777: Triple seven, triple failure.",
892 }, ctx.FullCommand)
893 }
894 if num == 666 {
895 return "chmod 666: Devil's permission for devilish code."
896 }
897 if num == 000 || num == 0 {
898 return "chmod 000: Like your access to competence."
899 }
900
901 // Kill signals
902 if num == 9 {
903 return selectInsult([]string{
904 "kill -9: Killing process. Can't kill your incompetence.",
905 "SIGKILL sent: Signal your career is over.",
906 }, ctx.FullCommand)
907 }
908
909 return ""
910 }
911
912 // getShellInsult returns insults based on shell type
913 func getShellInsult(ctx SmartFallbackContext) string {
914 shell := strings.ToLower(ctx.Shell)
915
916 shellInsults := map[string][]string{
917 "bash": {
918 "Bash error: Bash your head against keyboard, same result.",
919 "Bourne Again Shell: Borne to fail again.",
920 },
921 "zsh": {
922 "Z shell: Z for Zero competence level.",
923 "Zsh failure: Last shell of the alphabet, last in skill.",
924 },
925 "fish": {
926 "Fish shell: You're swimming in failure.",
927 "Fish error: Fishing for competence, caught nothing.",
928 },
929 "sh": {
930 "Bourne shell: Born to fail.",
931 "sh: Should've stayed in the shell.",
932 },
933 "ksh": {
934 "Korn shell: Your code is corny.",
935 },
936 "csh": {
937 "C shell: See? Shell of incompetence.",
938 },
939 }
940
941 if insults, exists := shellInsults[shell]; exists {
942 return selectInsult(insults, ctx.FullCommand)
943 }
944
945 return ""
946 }
947
948 // getCommandComplexityInsult returns insults based on command complexity
949 func getCommandComplexityInsult(ctx SmartFallbackContext) string {
950 length := ctx.CommandLength
951
952 if length < 10 {
953 return selectInsult([]string{
954 "Short command, short career.",
955 "Simple command failed: Simply incompetent.",
956 }, ctx.FullCommand)
957 }
958
959 if length > 100 {
960 return selectInsult([]string{
961 "Command longer than your employment prospects.",
962 "100+ characters: Complexity hiding incompetence.",
963 "Long command: Compensating for short skills.",
964 }, ctx.FullCommand)
965 }
966
967 if ctx.HasPipes && ctx.HasChaining {
968 return selectInsult([]string{
969 "Pipes AND chaining? Piping chained disasters together.",
970 "Complex piped chain: Complexly incompetent.",
971 }, ctx.FullCommand)
972 }
973
974 if ctx.HasPipes {
975 return selectInsult([]string{
976 "Pipe fail: Piping garbage to garbage.",
977 "Pipeline broken: Like your career pipeline.",
978 }, ctx.FullCommand)
979 }
980
981 if ctx.HasChaining {
982 return selectInsult([]string{
983 "Chaining commands: Chaining failures sequentially.",
984 "&& operator: AND you're terrible AND incompetent.",
985 }, ctx.FullCommand)
986 }
987
988 return ""
989 }
990
991 // Tier 2 Intelligence Detection Functions
992
993 // detectGitBranch detects the current git branch
994 func detectGitBranch() string {
995 // Check if we're in a git repo first
996 if _, err := os.Stat(".git"); os.IsNotExist(err) {
997 return ""
998 }
999
1000 // Try to get current branch
1001 if data, err := os.ReadFile(".git/HEAD"); err == nil {
1002 head := string(data)
1003 // Format: "ref: refs/heads/branch-name"
1004 if strings.HasPrefix(head, "ref: refs/heads/") {
1005 branch := strings.TrimPrefix(head, "ref: refs/heads/")
1006 return strings.TrimSpace(branch)
1007 }
1008 }
1009
1010 return ""
1011 }
1012
1013 // detectProjectType detects project type by checking for common project files
1014 func detectProjectType() (string, []string) {
1015 projectFiles := []string{
1016 "package.json", // Node.js
1017 "Cargo.toml", // Rust
1018 "go.mod", // Go
1019 "requirements.txt", // Python
1020 "Pipfile", // Python (pipenv)
1021 "pyproject.toml", // Python (poetry)
1022 "pom.xml", // Java (Maven)
1023 "build.gradle", // Java (Gradle)
1024 "Gemfile", // Ruby
1025 "composer.json", // PHP
1026 "Makefile", // C/C++
1027 "CMakeLists.txt", // C/C++ (CMake)
1028 "package.swift", // Swift
1029 "mix.exs", // Elixir
1030 "Dockerfile", // Docker
1031 "docker-compose.yml", // Docker Compose
1032 }
1033
1034 var foundFiles []string
1035 for _, file := range projectFiles {
1036 if _, err := os.Stat(file); err == nil {
1037 foundFiles = append(foundFiles, file)
1038 }
1039 }
1040
1041 // Determine project type from found files
1042 if len(foundFiles) == 0 {
1043 return "", nil
1044 }
1045
1046 // Priority order for type detection
1047 typeMap := map[string]string{
1048 "package.json": "node",
1049 "Cargo.toml": "rust",
1050 "go.mod": "go",
1051 "requirements.txt": "python",
1052 "Pipfile": "python",
1053 "pyproject.toml": "python",
1054 "pom.xml": "java",
1055 "build.gradle": "java",
1056 "Gemfile": "ruby",
1057 "composer.json": "php",
1058 "package.swift": "swift",
1059 "mix.exs": "elixir",
1060 }
1061
1062 for _, file := range foundFiles {
1063 if projectType, exists := typeMap[file]; exists {
1064 return projectType, foundFiles
1065 }
1066 }
1067
1068 return "generic", foundFiles
1069 }
1070
1071 // getGitBranchInsult returns insults based on git branch
1072 func getGitBranchInsult(ctx SmartFallbackContext) string {
1073 if ctx.GitBranch == "" {
1074 return ""
1075 }
1076
1077 branch := strings.ToLower(ctx.GitBranch)
1078
1079 branchInsults := map[string][]string{
1080 "main": {
1081 "Breaking main? Breaking everyone's day.",
1082 "Main branch failure: Main character of disasters.",
1083 "Failed on main: Mainly incompetent.",
1084 "Main branch disaster: You're the main problem.",
1085 },
1086 "master": {
1087 "Master branch failure: Master of disasters.",
1088 "Breaking master: Mastering incompetence.",
1089 "Master branch error: You've mastered failure.",
1090 },
1091 "develop": {
1092 "Develop branch failed: Develop your skills first.",
1093 "Development branch: Under-developed skills.",
1094 "Develop? More like devolve.",
1095 },
1096 "dev": {
1097 "Dev branch failed: Dev-astating incompetence.",
1098 "Dev environment: Environment of failure.",
1099 },
1100 "staging": {
1101 "Staging failure: Staging your resignation.",
1102 "Staging branch: Staging area for disaster.",
1103 },
1104 "production": {
1105 "Production branch failed: Producing unemployment.",
1106 "Prod branch error: Professionally regressive.",
1107 },
1108 }
1109
1110 // Check exact matches first
1111 if insults, exists := branchInsults[branch]; exists {
1112 return selectInsult(insults, ctx.FullCommand)
1113 }
1114
1115 // Check for patterns
1116 if strings.Contains(branch, "feature") || strings.HasPrefix(branch, "feat/") {
1117 return selectInsult([]string{
1118 "Feature branch: Featured failure.",
1119 "New feature: Newly incompetent.",
1120 "Feature branch failed: Feature: Broken. Developer: Broken.",
1121 }, ctx.FullCommand)
1122 }
1123
1124 if strings.Contains(branch, "hotfix") || strings.HasPrefix(branch, "fix/") {
1125 return selectInsult([]string{
1126 "Hotfix branch: You ARE the bug.",
1127 "Hotfix failed: Can't fix what's fundamentally broken: You.",
1128 "Hotfix? More like hot mess.",
1129 }, ctx.FullCommand)
1130 }
1131
1132 if strings.Contains(branch, "bugfix") || strings.Contains(branch, "bug/") {
1133 return selectInsult([]string{
1134 "Bugfix branch: The bug is you.",
1135 "Fixing bugs? You ARE the bug.",
1136 }, ctx.FullCommand)
1137 }
1138
1139 if strings.Contains(branch, "release") {
1140 return selectInsult([]string{
1141 "Release branch failed: Release your grip on keyboard.",
1142 "Release branch: Releasing disaster into the world.",
1143 }, ctx.FullCommand)
1144 }
1145
1146 if strings.Contains(branch, "test") {
1147 return selectInsult([]string{
1148 "Test branch failed: You're the test, reality failed you.",
1149 "Testing branch: Test results: FAIL.",
1150 }, ctx.FullCommand)
1151 }
1152
1153 return ""
1154 }
1155
1156 // getProjectTypeInsult returns insults based on detected project type
1157 func getProjectTypeInsult(ctx SmartFallbackContext) string {
1158 if ctx.ProjectType == "" {
1159 return ""
1160 }
1161
1162 projectInsults := map[string][]string{
1163 "node": {
1164 "Node project detected. Dependencies: Many. Skills: None.",
1165 "package.json found: Package of failures.",
1166 "Node.js project: Node your way out of this one.",
1167 "npm detected: Node Package Misery.",
1168 },
1169 "rust": {
1170 "Cargo.toml found: Can't cargo your incompetence.",
1171 "Rust project detected: Rust in peace, code.",
1172 "Cargo workspace: Working on failure.",
1173 },
1174 "go": {
1175 "go.mod found: Go away.",
1176 "Go project detected: Should've gone into another career.",
1177 "Go modules: Modular incompetence.",
1178 },
1179 "python": {
1180 "requirements.txt found: Requirement for skill: UNMET.",
1181 "Python project detected: Snake bit you back.",
1182 "Python dependencies: Depending on incompetence.",
1183 "Virtual environment detected: Can't isolate stupidity.",
1184 },
1185 "java": {
1186 "pom.xml found: Maven project: Mav-un successful.",
1187 "Java project detected: Needs more than coffee.",
1188 "Gradle detected: Grade: F. Project: Failed.",
1189 },
1190 "ruby": {
1191 "Gemfile found: Cubic zirconia skills.",
1192 "Ruby project: Ruby red with embarrassment.",
1193 "Bundler detected: Bundle of incompetence.",
1194 },
1195 "php": {
1196 "composer.json found: Can't compose competence.",
1197 "PHP project: Probably Horrible Programming detected.",
1198 },
1199 "swift": {
1200 "Swift project: Swift path to unemployment.",
1201 "Package.swift found: Swiftly failing.",
1202 },
1203 "elixir": {
1204 "Elixir project: No elixir can cure this.",
1205 "mix.exs found: Mixed results: All bad.",
1206 },
1207 }
1208
1209 if insults, exists := projectInsults[ctx.ProjectType]; exists {
1210 return selectInsult(insults, ctx.FullCommand)
1211 }
1212
1213 return ""
1214 }
1215
1216 // selectInsult picks an insult using pseudo-random selection
1217 func selectInsult(insults []string, seed string) string {
1218 if len(insults) == 0 {
1219 return ""
1220 }
1221
1222 hash := 0
1223 for _, char := range seed {
1224 hash = hash*31 + int(char)
1225 }
1226 if hash < 0 {
1227 hash = -hash
1228 }
1229
1230 return insults[hash%len(insults)]
1231 }
1232
1233 // ============================================================================
1234 // TIER 3 INTELLIGENCE - Advanced LLM-like Context Awareness
1235 // ============================================================================
1236
1237 // fileExists checks if a file exists
1238 func fileExists(filename string) bool {
1239 _, err := os.Stat(filename)
1240 return err == nil
1241 }
1242
1243 // detectCIEnvironment detects if running in CI/CD
1244 func detectCIEnvironment(env map[string]string) (bool, string) {
1245 ciChecks := map[string]string{
1246 "GITHUB_ACTIONS": "github",
1247 "GITLAB_CI": "gitlab",
1248 "JENKINS_HOME": "jenkins",
1249 "CIRCLECI": "circle",
1250 "TRAVIS": "travis",
1251 "CI": "generic",
1252 }
1253
1254 for envVar, provider := range ciChecks {
1255 if _, exists := env[envVar]; exists {
1256 return true, provider
1257 }
1258 }
1259
1260 return false, ""
1261 }
1262
1263 // estimateDependencyCount estimates project complexity
1264 func estimateDependencyCount(projectType string) int {
1265 switch projectType {
1266 case "node":
1267 // Check package.json for rough count
1268 if data, err := os.ReadFile("package.json"); err == nil {
1269 // Rough heuristic: count dependencies and devDependencies
1270 count := strings.Count(string(data), `"dependencies"`)
1271 count += strings.Count(string(data), `"devDependencies"`)
1272 if count > 0 {
1273 // Estimate ~20-100 deps if sections exist
1274 return 50
1275 }
1276 }
1277 case "rust":
1278 if data, err := os.ReadFile("Cargo.toml"); err == nil {
1279 // Count [dependencies] entries
1280 deps := strings.Count(string(data), "\n") / 3
1281 return deps
1282 }
1283 case "go":
1284 if data, err := os.ReadFile("go.mod"); err == nil {
1285 // Count require statements
1286 deps := strings.Count(string(data), "require")
1287 return deps
1288 }
1289 case "python":
1290 if data, err := os.ReadFile("requirements.txt"); err == nil {
1291 // Count lines
1292 deps := strings.Count(string(data), "\n")
1293 return deps
1294 }
1295 }
1296 return 0
1297 }
1298
1299 // detectErrorPattern recognizes common error patterns
1300 func detectErrorPattern(exitCode int, command string) string {
1301 // Map exit codes to error patterns
1302 patterns := map[int]string{
1303 1: "general_error",
1304 2: "misuse",
1305 126: "permission_denied",
1306 127: "command_not_found",
1307 128: "invalid_exit",
1308 130: "ctrl_c",
1309 137: "killed",
1310 139: "segfault",
1311 143: "sigterm",
1312 255: "network_error",
1313 }
1314
1315 if pattern, exists := patterns[exitCode]; exists {
1316 return pattern
1317 }
1318
1319 // Pattern detection from command content
1320 cmdLower := strings.ToLower(command)
1321 if strings.Contains(cmdLower, "permission") || strings.Contains(cmdLower, "denied") {
1322 return "permission_denied"
1323 }
1324 if strings.Contains(cmdLower, "connection") || strings.Contains(cmdLower, "refused") {
1325 return "connection_refused"
1326 }
1327 if strings.Contains(cmdLower, "timeout") {
1328 return "timeout"
1329 }
1330 if strings.Contains(cmdLower, "not found") || strings.Contains(cmdLower, "404") {
1331 return "not_found"
1332 }
1333
1334 return ""
1335 }
1336
1337 // failureTracker stores recent command failures (simple in-process tracking)
1338 var failureTracker = make(map[string]int)
1339
1340 // trackFailure tracks command failures and detects repeats
1341 func trackFailure(command string) bool {
1342 // Create a simple hash of the command
1343 hash := 0
1344 for _, char := range command {
1345 hash = hash*31 + int(char)
1346 }
1347 cmdHash := strconv.Itoa(hash)
1348
1349 // Increment failure count
1350 failureTracker[cmdHash]++
1351
1352 // Consider it repeated if failed 2+ times
1353 return failureTracker[cmdHash] >= 2
1354 }
1355
1356 // getRepeatedFailureInsult returns escalated insults for repeated failures
1357 func getRepeatedFailureInsult(ctx SmartFallbackContext) string {
1358 if !ctx.IsRepeatedFailure {
1359 return ""
1360 }
1361
1362 insults := []string{
1363 "Same command, same failure. Definition of insanity.",
1364 "Trying again? Einstein called: That's insanity.",
1365 "Repeated failure detected. Time to try reading docs.",
1366 "Still failing? Maybe it's not the computer.",
1367 "Second time's the charm? Not for you.",
1368 "Failure #2: The sequel nobody asked for.",
1369 "Doing it again won't make it work. Won't make you smarter either.",
1370 "Another attempt, another disaster. Predictable.",
1371 "Groundhog Day: The Failure Edition.",
1372 "Learning from mistakes requires learning.",
1373 "Try, fail, repeat. The three-step program to nowhere.",
1374 "Persistence is admirable. Persistent incompetence isn't.",
1375 "You're very consistent. Consistently wrong.",
1376 "Same command, different hour, identical disaster.",
1377 "Repeating mistakes: The one skill you've mastered.",
1378 }
1379
1380 return selectInsult(insults, ctx.FullCommand)
1381 }
1382
1383 // getCIInsult returns CI/CD-specific insults
1384 func getCIInsult(ctx SmartFallbackContext) string {
1385 if !ctx.IsCI {
1386 return ""
1387 }
1388
1389 ciInsults := map[string][]string{
1390 "github": {
1391 "Breaking GitHub Actions? Breaking everyone's sprint.",
1392 "GitHub Actions failed: Your actions speak volumes.",
1393 "GH Actions: Great Humiliation Actions.",
1394 "Failed in CI: Continuous Integration of Disaster.",
1395 "GitHub Actions: Git blame yourself.",
1396 },
1397 "gitlab": {
1398 "GitLab CI failed: Commit to unemployment.",
1399 "Pipeline broken: Your career too.",
1400 "GitLab runner failed: Run from development.",
1401 "CI/CD failed: Career Imminent Cancellation Detected.",
1402 },
1403 "jenkins": {
1404 "Jenkins job failed: Job security failed.",
1405 "Build #404: Competence not found.",
1406 "Jenkins says: Build career, not this garbage.",
1407 "Red build: Your face should match.",
1408 },
1409 "circle": {
1410 "CircleCI failed: Circle of failure complete.",
1411 "Workflow failed: Work towards new career flow.",
1412 "Circle CI: Circular logic detected.",
1413 },
1414 "travis": {
1415 "Travis CI broken: Travis-ty of errors.",
1416 "Build failed: Career build deprecated.",
1417 },
1418 "generic": {
1419 "CI failed: Continuous Integration? Continuous Incompetence.",
1420 "Breaking the build: Breaking your team's trust.",
1421 "Failed in CI: Everyone can see your shame.",
1422 "Pipeline blocked: By your incompetence.",
1423 },
1424 }
1425
1426 if insults, exists := ciInsults[ctx.CIProvider]; exists {
1427 return selectInsult(insults, ctx.FullCommand)
1428 }
1429
1430 return ""
1431 }
1432
1433 // getErrorPatternInsult returns pattern-specific insults
1434 func getErrorPatternInsult(ctx SmartFallbackContext) string {
1435 if ctx.ErrorPattern == "" {
1436 return ""
1437 }
1438
1439 patternInsults := map[string][]string{
1440 "permission_denied": {
1441 "Permission denied: Denied access to competence too.",
1442 "No permission: No skill either.",
1443 "sudo won't fix this level of incompetence.",
1444 "Access denied: Reality denying you success.",
1445 "Insufficient permissions: Insufficient everything.",
1446 },
1447 "command_not_found": {
1448 "Command not found: Competence not found.",
1449 "404: Command missing. Also: Your skill.",
1450 "Command not found: Try 'find-new-career'.",
1451 "PATH searched: Competence not in PATH.",
1452 },
1453 "connection_refused": {
1454 "Connection refused: Server refused your incompetence.",
1455 "Connection denied: Denied by reality.",
1456 "Can't connect: Reality disconnecting from you.",
1457 "Connection refused: Even localhost rejects you.",
1458 },
1459 "timeout": {
1460 "Timeout: Even the computer gave up waiting.",
1461 "Request timed out: So did patience.",
1462 "Timeout: Time to consider new profession.",
1463 "Connection timeout: Career timeout imminent.",
1464 },
1465 "segfault": {
1466 "Segmentation fault: Segmented from reality.",
1467 "Segfault: Memory accessed. Memory of competence: Not found.",
1468 "Core dumped: Core competence: Also dumped.",
1469 "Segfault: Your code violated everything.",
1470 },
1471 "killed": {
1472 "Process killed: Career should be too.",
1473 "Killed by signal: Signaling incompetence.",
1474 "SIGKILL received: Kill switch on career recommended.",
1475 },
1476 "not_found": {
1477 "Not found: Your skill is also 404.",
1478 "404: Not found. Unlike your incompetence: Always 200 OK.",
1479 "Resource not found: Resources for learning: Also not found.",
1480 },
1481 }
1482
1483 if insults, exists := patternInsults[ctx.ErrorPattern]; exists {
1484 return selectInsult(insults, ctx.FullCommand)
1485 }
1486
1487 return ""
1488 }
1489
1490 // getBuildSystemInsult returns build tool specific insults
1491 func getBuildSystemInsult(ctx SmartFallbackContext) string {
1492 insults := []string{}
1493
1494 if ctx.HasDockerfile {
1495 insults = append(insults,
1496 "Dockerfile detected: Can't containerize competence.",
1497 "Docker build failed: Image of failure created.",
1498 "Container crashed: Can't contain your mistakes.",
1499 "Dockerfile present: Should've dockerized your career away.",
1500 )
1501 }
1502
1503 if ctx.HasMakefile {
1504 insults = append(insults,
1505 "Makefile found: Make disasters, not software.",
1506 "make failed: Made a mistake becoming a developer.",
1507 "Build system detected: System detected you.",
1508 )
1509 }
1510
1511 if len(insults) > 0 {
1512 return selectInsult(insults, ctx.FullCommand)
1513 }
1514
1515 return ""
1516 }
1517
1518 // getDependencyInsult returns complexity-aware insults
1519 func getDependencyInsult(ctx SmartFallbackContext) string {
1520 if ctx.DependencyCount == 0 {
1521 return ""
1522 }
1523
1524 var insults []string
1525
1526 if ctx.DependencyCount > 100 {
1527 insults = []string{
1528 "100+ dependencies: Depending on others for your failures.",
1529 "Dependency hell: You're everyone's least favorite dependency.",
1530 "Massive dependency tree: Tree of incompetence.",
1531 "Dependencies: Hundreds. Competence: Zero.",
1532 }
1533 } else if ctx.DependencyCount > 20 {
1534 insults = []string{
1535 "Dependencies detected: You depend on failure.",
1536 "Package.json bloated: Like your ego, unlike your skill.",
1537 "Dependency count high: Skill count low.",
1538 "Many dependencies: None can fix this.",
1539 }
1540 }
1541
1542 if len(insults) > 0 {
1543 return selectInsult(insults, ctx.FullCommand)
1544 }
1545
1546 return ""
1547 }
1548
1549 // ============================================================================
1550 // TIER 5 INTELLIGENCE - Hybrid Ensemble ML System
1551 // ============================================================================
1552 // Combines TF-IDF semantic similarity, Markov chain generation, tag-based
1553 // scoring, and historical pattern matching with ensemble voting.
1554
1555 // generateMLInsult uses the hybrid ensemble system to select/generate the best insult
1556 func generateMLInsult(ctx SmartFallbackContext) string {
1557 // Determine personality from config (default to sarcastic)
1558 personality := "sarcastic"
1559 if config := LoadConfig(); config != nil && config.General.Personality != "" {
1560 personality = config.General.Personality
1561 }
1562
1563 // Use the powerful ensemble system that combines:
1564 // - TF-IDF semantic similarity (cosine similarity)
1565 // - Tag-based matching (existing system)
1566 // - Markov chain generation (novel insults)
1567 // - Historical pattern learning
1568 // - Novelty scoring (avoid repetition)
1569 // - Weighted ensemble voting
1570 insult := ensembleSystem.GenerateInsult(&ctx, personality)
1571
1572 if insult == "" {
1573 return "" // Fall through to other tiers
1574 }
1575
1576 return insult
1577 }
1578
1579 // LoadConfig loads the parrot configuration (stub - integrate with actual config)
1580 func LoadConfig() *Config {
1581 // This should integrate with the actual config loader
1582 // For now, return nil to use defaults
1583 return nil
1584 }
1585
1586 // Config represents parrot configuration
1587 type Config struct {
1588 General GeneralConfig
1589 }
1590
1591 // GeneralConfig represents general configuration
1592 type GeneralConfig struct {
1593 Personality string
1594 }
1595