@softspark/ai-toolkit 1.0.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.
- package/AGENTS.md +412 -0
- package/CHANGELOG.md +68 -0
- package/LICENSE +21 -0
- package/README.md +632 -0
- package/action.yml +53 -0
- package/app/.claude-plugin/plugin.json +44 -0
- package/app/ARCHITECTURE.md +306 -0
- package/app/CLAUDE.md.template +23 -0
- package/app/agents/ai-engineer.md +128 -0
- package/app/agents/backend-specialist.md +193 -0
- package/app/agents/business-intelligence.md +54 -0
- package/app/agents/chaos-monkey.md +67 -0
- package/app/agents/chief-of-staff.md +51 -0
- package/app/agents/code-archaeologist.md +127 -0
- package/app/agents/code-reviewer.md +184 -0
- package/app/agents/command-expert.md +131 -0
- package/app/agents/data-analyst.md +205 -0
- package/app/agents/data-scientist.md +151 -0
- package/app/agents/database-architect.md +317 -0
- package/app/agents/debugger.md +238 -0
- package/app/agents/devops-implementer.md +194 -0
- package/app/agents/documenter.md +364 -0
- package/app/agents/explorer-agent.md +145 -0
- package/app/agents/fact-checker.md +172 -0
- package/app/agents/frontend-specialist.md +209 -0
- package/app/agents/game-developer.md +216 -0
- package/app/agents/incident-responder.md +226 -0
- package/app/agents/infrastructure-architect.md +127 -0
- package/app/agents/infrastructure-validator.md +247 -0
- package/app/agents/llm-ops-engineer.md +237 -0
- package/app/agents/mcp-expert.md +228 -0
- package/app/agents/mcp-server-architect.md +195 -0
- package/app/agents/mcp-testing-engineer.md +292 -0
- package/app/agents/meta-architect.md +58 -0
- package/app/agents/ml-engineer.md +136 -0
- package/app/agents/mobile-developer.md +190 -0
- package/app/agents/night-watchman.md +55 -0
- package/app/agents/nlp-engineer.md +154 -0
- package/app/agents/orchestrator.md +437 -0
- package/app/agents/performance-optimizer.md +254 -0
- package/app/agents/predictive-analyst.md +57 -0
- package/app/agents/product-manager.md +194 -0
- package/app/agents/project-planner.md +287 -0
- package/app/agents/prompt-engineer.md +103 -0
- package/app/agents/qa-automation-engineer.md +182 -0
- package/app/agents/rag-engineer.md +201 -0
- package/app/agents/research-synthesizer.md +138 -0
- package/app/agents/search-specialist.md +101 -0
- package/app/agents/security-architect.md +62 -0
- package/app/agents/security-auditor.md +293 -0
- package/app/agents/seo-specialist.md +111 -0
- package/app/agents/system-governor.md +57 -0
- package/app/agents/tech-lead.md +62 -0
- package/app/agents/technical-researcher.md +103 -0
- package/app/agents/test-engineer.md +264 -0
- package/app/constitution.md +38 -0
- package/app/hooks/_profile-check.sh +11 -0
- package/app/hooks/guard-destructive.sh +74 -0
- package/app/hooks/guard-path.sh +73 -0
- package/app/hooks/post-tool-use.sh +35 -0
- package/app/hooks/pre-compact.sh +31 -0
- package/app/hooks/quality-check.sh +22 -0
- package/app/hooks/quality-gate.sh +49 -0
- package/app/hooks/save-session.sh +24 -0
- package/app/hooks/session-end.sh +37 -0
- package/app/hooks/session-start.sh +29 -0
- package/app/hooks/subagent-start.sh +16 -0
- package/app/hooks/subagent-stop.sh +16 -0
- package/app/hooks/track-usage.sh +50 -0
- package/app/hooks/user-prompt-submit.sh +25 -0
- package/app/hooks.json +178 -0
- package/app/mcp-defaults.json +23 -0
- package/app/output-styles/golden-rules.md +43 -0
- package/app/plugins/README.md +19 -0
- package/app/plugins/csharp-pack/README.md +11 -0
- package/app/plugins/csharp-pack/plugin.json +18 -0
- package/app/plugins/enterprise-pack/README.md +16 -0
- package/app/plugins/enterprise-pack/hooks/output-style.sh +6 -0
- package/app/plugins/enterprise-pack/hooks/status-line.sh +8 -0
- package/app/plugins/enterprise-pack/plugin.json +24 -0
- package/app/plugins/frontend-pack/README.md +14 -0
- package/app/plugins/frontend-pack/plugin.json +22 -0
- package/app/plugins/java-pack/README.md +11 -0
- package/app/plugins/java-pack/plugin.json +18 -0
- package/app/plugins/kotlin-pack/README.md +11 -0
- package/app/plugins/kotlin-pack/plugin.json +18 -0
- package/app/plugins/memory-pack/README.md +24 -0
- package/app/plugins/memory-pack/hooks/observation-capture.sh +67 -0
- package/app/plugins/memory-pack/hooks/session-summary.sh +71 -0
- package/app/plugins/memory-pack/plugin.json +22 -0
- package/app/plugins/memory-pack/scripts/init_db.py +81 -0
- package/app/plugins/memory-pack/scripts/strip_private.py +22 -0
- package/app/plugins/memory-pack/skills/mem-search/SKILL.md +70 -0
- package/app/plugins/research-pack/README.md +14 -0
- package/app/plugins/research-pack/plugin.json +22 -0
- package/app/plugins/ruby-pack/README.md +11 -0
- package/app/plugins/ruby-pack/plugin.json +18 -0
- package/app/plugins/rust-pack/README.md +11 -0
- package/app/plugins/rust-pack/plugin.json +18 -0
- package/app/plugins/security-pack/README.md +15 -0
- package/app/plugins/security-pack/plugin.json +23 -0
- package/app/plugins/swift-pack/README.md +11 -0
- package/app/plugins/swift-pack/plugin.json +18 -0
- package/app/rules/claude-toolkit-rules.md +21 -0
- package/app/rules/git-conventions.md +5 -0
- package/app/rules/quality-gates.md +10 -0
- package/app/skills/_lib/__init__.py +1 -0
- package/app/skills/_lib/detect_utils.py +150 -0
- package/app/skills/agent-creator/SKILL.md +82 -0
- package/app/skills/analyze/SKILL.md +92 -0
- package/app/skills/analyze/scripts/complexity.py +165 -0
- package/app/skills/api-patterns/SKILL.md +305 -0
- package/app/skills/app-builder/SKILL.md +187 -0
- package/app/skills/architecture-audit/SKILL.md +141 -0
- package/app/skills/architecture-decision/SKILL.md +55 -0
- package/app/skills/architecture-decision/templates/adr-template.md +36 -0
- package/app/skills/biz-scan/SKILL.md +30 -0
- package/app/skills/briefing/SKILL.md +27 -0
- package/app/skills/build/SKILL.md +97 -0
- package/app/skills/build/scripts/detect-build.py +151 -0
- package/app/skills/chaos/SKILL.md +32 -0
- package/app/skills/ci/SKILL.md +77 -0
- package/app/skills/ci/scripts/ci-detect.py +135 -0
- package/app/skills/ci/templates/github-actions-node.yml +38 -0
- package/app/skills/ci/templates/github-actions-python.yml +42 -0
- package/app/skills/ci-cd-patterns/SKILL.md +299 -0
- package/app/skills/clean-code/SKILL.md +110 -0
- package/app/skills/clean-code/reference/dart.md +18 -0
- package/app/skills/clean-code/reference/go.md +23 -0
- package/app/skills/clean-code/reference/php.md +32 -0
- package/app/skills/clean-code/reference/python.md +180 -0
- package/app/skills/clean-code/reference/typescript.md +26 -0
- package/app/skills/command-creator/SKILL.md +83 -0
- package/app/skills/commit/SKILL.md +98 -0
- package/app/skills/commit/scripts/pre-commit-check.py +87 -0
- package/app/skills/commit/templates/conventional-commit.md +52 -0
- package/app/skills/csharp-patterns/SKILL.md +450 -0
- package/app/skills/database-patterns/SKILL.md +297 -0
- package/app/skills/debug/SKILL.md +154 -0
- package/app/skills/debug/scripts/error-parser.py +187 -0
- package/app/skills/debugging-tactics/SKILL.md +136 -0
- package/app/skills/deploy/SKILL.md +130 -0
- package/app/skills/deploy/scripts/pre_deploy_check.py +171 -0
- package/app/skills/deploy/templates/deployment-checklist.md +31 -0
- package/app/skills/design-an-interface/SKILL.md +105 -0
- package/app/skills/design-engineering/SKILL.md +260 -0
- package/app/skills/docker-devops/SKILL.md +303 -0
- package/app/skills/docs/SKILL.md +145 -0
- package/app/skills/docs/scripts/doc-inventory.py +176 -0
- package/app/skills/docs/templates/adr-template.md +36 -0
- package/app/skills/docs/templates/readme-template.md +67 -0
- package/app/skills/documentation-standards/SKILL.md +191 -0
- package/app/skills/ecommerce-patterns/SKILL.md +209 -0
- package/app/skills/evaluate/SKILL.md +132 -0
- package/app/skills/evolve/SKILL.md +27 -0
- package/app/skills/explain/SKILL.md +54 -0
- package/app/skills/explain/scripts/dependency-graph.py +215 -0
- package/app/skills/explore/SKILL.md +112 -0
- package/app/skills/explore/scripts/visualize.py +117 -0
- package/app/skills/fix/SKILL.md +78 -0
- package/app/skills/fix/scripts/error-classifier.py +191 -0
- package/app/skills/flutter-patterns/SKILL.md +254 -0
- package/app/skills/git-mastery/SKILL.md +70 -0
- package/app/skills/grill-me/SKILL.md +38 -0
- package/app/skills/health/SKILL.md +91 -0
- package/app/skills/health/scripts/health_check.py +162 -0
- package/app/skills/hive-mind/SKILL.md +56 -0
- package/app/skills/hook-creator/SKILL.md +107 -0
- package/app/skills/index/SKILL.md +74 -0
- package/app/skills/instinct-review/SKILL.md +77 -0
- package/app/skills/java-patterns/SKILL.md +442 -0
- package/app/skills/kotlin-patterns/SKILL.md +446 -0
- package/app/skills/lint/SKILL.md +103 -0
- package/app/skills/lint/scripts/detect-linters.py +112 -0
- package/app/skills/mcp-patterns/SKILL.md +270 -0
- package/app/skills/mem-search/SKILL.md +70 -0
- package/app/skills/migrate/SKILL.md +90 -0
- package/app/skills/migrate/scripts/migration-status.py +195 -0
- package/app/skills/migration-patterns/SKILL.md +260 -0
- package/app/skills/night-watch/SKILL.md +28 -0
- package/app/skills/observability-patterns/SKILL.md +203 -0
- package/app/skills/onboard/SKILL.md +76 -0
- package/app/skills/orchestrate/SKILL.md +86 -0
- package/app/skills/panic/SKILL.md +30 -0
- package/app/skills/performance-profiling/SKILL.md +59 -0
- package/app/skills/plan/SKILL.md +110 -0
- package/app/skills/plan/templates/plan-template.md +40 -0
- package/app/skills/plan-writing/SKILL.md +201 -0
- package/app/skills/plugin-creator/SKILL.md +78 -0
- package/app/skills/pr/SKILL.md +129 -0
- package/app/skills/pr/scripts/pr-summary.py +175 -0
- package/app/skills/prd-to-issues/SKILL.md +108 -0
- package/app/skills/prd-to-plan/SKILL.md +120 -0
- package/app/skills/predict/SKILL.md +30 -0
- package/app/skills/qa-session/SKILL.md +110 -0
- package/app/skills/rag-patterns/SKILL.md +203 -0
- package/app/skills/refactor/SKILL.md +124 -0
- package/app/skills/refactor/scripts/refactor-scan.py +210 -0
- package/app/skills/refactor-plan/SKILL.md +112 -0
- package/app/skills/repeat/SKILL.md +149 -0
- package/app/skills/research-mastery/SKILL.md +56 -0
- package/app/skills/review/SKILL.md +141 -0
- package/app/skills/review/scripts/diff-analyzer.py +170 -0
- package/app/skills/rollback/SKILL.md +87 -0
- package/app/skills/rollback/scripts/rollback_info.py +149 -0
- package/app/skills/ruby-patterns/SKILL.md +454 -0
- package/app/skills/rust-patterns/SKILL.md +446 -0
- package/app/skills/search/SKILL.md +64 -0
- package/app/skills/security-patterns/SKILL.md +91 -0
- package/app/skills/security-patterns/reference/authentication.md +37 -0
- package/app/skills/security-patterns/reference/authorization.md +22 -0
- package/app/skills/security-patterns/reference/input-validation.md +30 -0
- package/app/skills/security-patterns/reference/oauth-csrf-audit.md +131 -0
- package/app/skills/skill-creator/SKILL.md +154 -0
- package/app/skills/skill-creator/templates/dashboard/index.html +130 -0
- package/app/skills/skill-creator/templates/reasoning-engine/assets/example.json +12 -0
- package/app/skills/skill-creator/templates/reasoning-engine/search.py +110 -0
- package/app/skills/subagent-development/SKILL.md +225 -0
- package/app/skills/subagent-development/reference/code-quality-reviewer-prompt.md +145 -0
- package/app/skills/subagent-development/reference/implementer-prompt.md +118 -0
- package/app/skills/subagent-development/reference/spec-reviewer-prompt.md +100 -0
- package/app/skills/swarm/SKILL.md +81 -0
- package/app/skills/swift-patterns/SKILL.md +500 -0
- package/app/skills/tdd/SKILL.md +174 -0
- package/app/skills/tdd/reference/deep-modules.md +32 -0
- package/app/skills/tdd/reference/interface-design.md +32 -0
- package/app/skills/tdd/reference/mocking.md +52 -0
- package/app/skills/tdd/reference/refactoring.md +10 -0
- package/app/skills/tdd/reference/tests.md +59 -0
- package/app/skills/teams/SKILL.md +101 -0
- package/app/skills/test/SKILL.md +107 -0
- package/app/skills/test/scripts/detect-runner.py +113 -0
- package/app/skills/testing-patterns/SKILL.md +73 -0
- package/app/skills/testing-patterns/reference/flutter-testing.md +33 -0
- package/app/skills/testing-patterns/reference/go-testing.md +52 -0
- package/app/skills/testing-patterns/reference/php-phpunit.md +39 -0
- package/app/skills/testing-patterns/reference/python-pytest.md +228 -0
- package/app/skills/testing-patterns/reference/typescript-vitest.md +50 -0
- package/app/skills/triage-issue/SKILL.md +120 -0
- package/app/skills/typescript-patterns/SKILL.md +256 -0
- package/app/skills/ubiquitous-language/SKILL.md +74 -0
- package/app/skills/verification-before-completion/SKILL.md +108 -0
- package/app/skills/workflow/SKILL.md +250 -0
- package/app/skills/write-a-prd/SKILL.md +129 -0
- package/app/skills/write-a-prd/reference/visual-companion.md +78 -0
- package/app/skills/write-a-prd/scripts/frame-template.html +111 -0
- package/app/skills/write-a-prd/scripts/visual-server.cjs +79 -0
- package/app/templates/skill/generator/SKILL.md.template +40 -0
- package/app/templates/skill/knowledge/SKILL.md.template +52 -0
- package/app/templates/skill/linter/SKILL.md.template +34 -0
- package/app/templates/skill/reviewer/SKILL.md.template +51 -0
- package/app/templates/skill/workflow/SKILL.md.template +49 -0
- package/benchmarks/README.md +111 -0
- package/benchmarks/ecosystem-dashboard.json +148 -0
- package/benchmarks/ecosystem-harvest.json +148 -0
- package/benchmarks/results.json +38 -0
- package/benchmarks/run.py +351 -0
- package/bin/ai-toolkit.js +345 -0
- package/kb/best-practices/README.md +11 -0
- package/kb/howto/README.md +11 -0
- package/kb/procedures/maintenance-sop.md +306 -0
- package/kb/reference/agents-catalog.md +124 -0
- package/kb/reference/anti-pattern-registry-format.md +221 -0
- package/kb/reference/architecture-overview.md +232 -0
- package/kb/reference/benchmark-config.md +62 -0
- package/kb/reference/ci-integration.md +66 -0
- package/kb/reference/claude-ecosystem-benchmark-snapshot.md +80 -0
- package/kb/reference/claude-ecosystem-expansion-foundations.md +102 -0
- package/kb/reference/commands-catalog.md +21 -0
- package/kb/reference/distribution-model.md +63 -0
- package/kb/reference/global-install-model.md +56 -0
- package/kb/reference/hierarchical-override-pattern.md +200 -0
- package/kb/reference/hooks-catalog.md +306 -0
- package/kb/reference/integrations.md +88 -0
- package/kb/reference/language-packs.md +52 -0
- package/kb/reference/merge-friendly-install-model.md +58 -0
- package/kb/reference/plugin-pack-conventions.md +151 -0
- package/kb/reference/quick-wins-implementation-summary.md +70 -0
- package/kb/reference/skill-templates.md +50 -0
- package/kb/reference/skills-catalog.md +215 -0
- package/kb/reference/skills-unification.md +57 -0
- package/kb/reference/stats.md +69 -0
- package/kb/reference/sync.md +76 -0
- package/kb/troubleshooting/README.md +11 -0
- package/llms-full.txt +3068 -0
- package/llms.txt +39 -0
- package/package.json +75 -0
- package/scripts/_common.py +160 -0
- package/scripts/add_rule.py +50 -0
- package/scripts/benchmark_config.py +127 -0
- package/scripts/benchmark_ecosystem.py +288 -0
- package/scripts/check_deps.py +260 -0
- package/scripts/create_skill.py +118 -0
- package/scripts/doctor.py +504 -0
- package/scripts/eject.py +113 -0
- package/scripts/emission.py +256 -0
- package/scripts/evaluate_skills.py +260 -0
- package/scripts/frontmatter.py +58 -0
- package/scripts/generate_agents_md.py +91 -0
- package/scripts/generate_aider_conf.py +51 -0
- package/scripts/generate_cline.py +35 -0
- package/scripts/generate_copilot.py +30 -0
- package/scripts/generate_cursor_rules.py +35 -0
- package/scripts/generate_gemini.py +28 -0
- package/scripts/generate_llms_txt.py +164 -0
- package/scripts/generate_roo_modes.py +80 -0
- package/scripts/generate_windsurf.py +35 -0
- package/scripts/generator_base.py +140 -0
- package/scripts/harvest_ecosystem.py +50 -0
- package/scripts/inject_rule_cli.py +101 -0
- package/scripts/inject_section_cli.py +47 -0
- package/scripts/injection.py +180 -0
- package/scripts/install.py +236 -0
- package/scripts/install_git_hooks.py +71 -0
- package/scripts/install_steps/__init__.py +5 -0
- package/scripts/install_steps/ai_tools.py +261 -0
- package/scripts/install_steps/hooks.py +90 -0
- package/scripts/install_steps/markers.py +79 -0
- package/scripts/install_steps/symlinks.py +87 -0
- package/scripts/merge-hooks.py +192 -0
- package/scripts/plugin.py +642 -0
- package/scripts/plugin_schema.py +138 -0
- package/scripts/remove_rule.py +58 -0
- package/scripts/stats.py +81 -0
- package/scripts/sync.py +215 -0
- package/scripts/uninstall.py +292 -0
- package/scripts/validate.py +700 -0
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: database-patterns
|
|
3
|
+
description: "Loaded when user asks about database schema or query optimization"
|
|
4
|
+
effort: medium
|
|
5
|
+
user-invocable: false
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Database Patterns Skill
|
|
9
|
+
|
|
10
|
+
## ORM Selection
|
|
11
|
+
|
|
12
|
+
| Scenario | ORM |
|
|
13
|
+
|----------|-----|
|
|
14
|
+
| Node.js, type-safe | Prisma |
|
|
15
|
+
| Node.js, SQL-first | Drizzle |
|
|
16
|
+
| Python, async | SQLAlchemy 2.0 |
|
|
17
|
+
| Python, simple | SQLModel |
|
|
18
|
+
| PHP | Doctrine, Eloquent |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Schema Design
|
|
23
|
+
|
|
24
|
+
### Naming Conventions
|
|
25
|
+
|
|
26
|
+
```sql
|
|
27
|
+
-- Tables: plural, snake_case
|
|
28
|
+
CREATE TABLE user_profiles (...);
|
|
29
|
+
|
|
30
|
+
-- Columns: snake_case
|
|
31
|
+
user_id, created_at, is_active
|
|
32
|
+
|
|
33
|
+
-- Indexes: idx_{table}_{columns}
|
|
34
|
+
CREATE INDEX idx_users_email ON users(email);
|
|
35
|
+
|
|
36
|
+
-- Foreign keys: fk_{table}_{ref_table}
|
|
37
|
+
CONSTRAINT fk_orders_users FOREIGN KEY (user_id) REFERENCES users(id)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Common Patterns
|
|
41
|
+
|
|
42
|
+
#### Soft Delete
|
|
43
|
+
```sql
|
|
44
|
+
ALTER TABLE users ADD COLUMN deleted_at TIMESTAMP NULL;
|
|
45
|
+
|
|
46
|
+
-- Query active records
|
|
47
|
+
SELECT * FROM users WHERE deleted_at IS NULL;
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
#### Audit Columns
|
|
51
|
+
```sql
|
|
52
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
53
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
54
|
+
created_by UUID REFERENCES users(id),
|
|
55
|
+
updated_by UUID REFERENCES users(id)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
#### UUID vs Serial
|
|
59
|
+
| Use Case | Type |
|
|
60
|
+
|----------|------|
|
|
61
|
+
| Internal only | SERIAL/BIGSERIAL |
|
|
62
|
+
| External/distributed | UUID |
|
|
63
|
+
| Human readable | SERIAL with prefix |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Index Strategies
|
|
68
|
+
|
|
69
|
+
### When to Index
|
|
70
|
+
- Foreign keys (always)
|
|
71
|
+
- Columns in WHERE clauses
|
|
72
|
+
- Columns in ORDER BY
|
|
73
|
+
- Columns in JOIN conditions
|
|
74
|
+
|
|
75
|
+
### Index Types
|
|
76
|
+
| Type | Use Case |
|
|
77
|
+
|------|----------|
|
|
78
|
+
| B-tree | Equality, range (default) |
|
|
79
|
+
| Hash | Equality only |
|
|
80
|
+
| GIN | Arrays, JSONB, full-text |
|
|
81
|
+
| GiST | Geometric, full-text |
|
|
82
|
+
| BRIN | Large sequential data |
|
|
83
|
+
|
|
84
|
+
### Composite Index Order
|
|
85
|
+
```sql
|
|
86
|
+
-- Good: matches query pattern
|
|
87
|
+
CREATE INDEX idx_orders_user_date ON orders(user_id, created_at);
|
|
88
|
+
SELECT * FROM orders WHERE user_id = 1 AND created_at > '2024-01-01';
|
|
89
|
+
|
|
90
|
+
-- Index used for:
|
|
91
|
+
-- WHERE user_id = 1
|
|
92
|
+
-- WHERE user_id = 1 AND created_at > ...
|
|
93
|
+
|
|
94
|
+
-- Index NOT used for:
|
|
95
|
+
-- WHERE created_at > '2024-01-01' (missing leading column)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Query Optimization
|
|
101
|
+
|
|
102
|
+
### Explain Analyze
|
|
103
|
+
```sql
|
|
104
|
+
EXPLAIN ANALYZE
|
|
105
|
+
SELECT * FROM users WHERE email = 'test@example.com';
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Common Issues
|
|
109
|
+
|
|
110
|
+
| Issue | Solution |
|
|
111
|
+
|-------|----------|
|
|
112
|
+
| Seq Scan on large table | Add index |
|
|
113
|
+
| High row estimate | Update statistics |
|
|
114
|
+
| Nested Loop on large sets | Consider hash join |
|
|
115
|
+
| Sort in memory | Increase work_mem |
|
|
116
|
+
|
|
117
|
+
### N+1 Prevention
|
|
118
|
+
```python
|
|
119
|
+
# Bad: N+1
|
|
120
|
+
for user in users:
|
|
121
|
+
print(user.orders) # Query per user
|
|
122
|
+
|
|
123
|
+
# Good: Eager loading
|
|
124
|
+
users = User.query.options(joinedload(User.orders)).all()
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Migration Best Practices
|
|
130
|
+
|
|
131
|
+
### Safe Migrations
|
|
132
|
+
```sql
|
|
133
|
+
-- Add column (safe)
|
|
134
|
+
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
|
|
135
|
+
|
|
136
|
+
-- Add NOT NULL column (safe pattern)
|
|
137
|
+
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
|
|
138
|
+
UPDATE users SET phone = '' WHERE phone IS NULL;
|
|
139
|
+
ALTER TABLE users ALTER COLUMN phone SET NOT NULL;
|
|
140
|
+
|
|
141
|
+
-- Rename column (use application-level)
|
|
142
|
+
-- 1. Add new column
|
|
143
|
+
-- 2. Copy data
|
|
144
|
+
-- 3. Update application
|
|
145
|
+
-- 4. Remove old column
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Migration Checklist
|
|
149
|
+
- [ ] Tested on production-like data
|
|
150
|
+
- [ ] Rollback script ready
|
|
151
|
+
- [ ] No long locks on large tables
|
|
152
|
+
- [ ] Indexes created concurrently
|
|
153
|
+
- [ ] Application handles both states
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Connection Pooling
|
|
158
|
+
|
|
159
|
+
### PgBouncer Settings
|
|
160
|
+
```ini
|
|
161
|
+
[pgbouncer]
|
|
162
|
+
pool_mode = transaction
|
|
163
|
+
max_client_conn = 1000
|
|
164
|
+
default_pool_size = 20
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Application Settings
|
|
168
|
+
| Framework | Pool Size Formula |
|
|
169
|
+
|-----------|------------------|
|
|
170
|
+
| General | (cores * 2) + disk spindles |
|
|
171
|
+
| Read-heavy | cores * 4 |
|
|
172
|
+
| Write-heavy | cores * 2 |
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Vector Database (Qdrant) Patterns
|
|
177
|
+
|
|
178
|
+
### Client Setup
|
|
179
|
+
```python
|
|
180
|
+
from qdrant_client import QdrantClient
|
|
181
|
+
from qdrant_client.models import Distance, VectorParams, PointStruct
|
|
182
|
+
|
|
183
|
+
# Sync client
|
|
184
|
+
client = QdrantClient(host="localhost", port=6333)
|
|
185
|
+
|
|
186
|
+
# Async client
|
|
187
|
+
from qdrant_client import AsyncQdrantClient
|
|
188
|
+
async_client = AsyncQdrantClient(host="localhost", port=6333)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Collection Management
|
|
192
|
+
```python
|
|
193
|
+
# Create collection (single vector)
|
|
194
|
+
client.create_collection(
|
|
195
|
+
collection_name="documents",
|
|
196
|
+
vectors_config=VectorParams(size=384, distance=Distance.COSINE)
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
# Create collection (multi-vector)
|
|
200
|
+
from qdrant_client.models import VectorParams
|
|
201
|
+
|
|
202
|
+
client.create_collection(
|
|
203
|
+
collection_name="multimodal",
|
|
204
|
+
vectors_config={
|
|
205
|
+
"text": VectorParams(size=384, distance=Distance.COSINE),
|
|
206
|
+
"image": VectorParams(size=512, distance=Distance.EUCLID),
|
|
207
|
+
}
|
|
208
|
+
)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Upserting Vectors
|
|
212
|
+
```python
|
|
213
|
+
# Single upsert
|
|
214
|
+
client.upsert(
|
|
215
|
+
collection_name="documents",
|
|
216
|
+
points=[
|
|
217
|
+
PointStruct(
|
|
218
|
+
id=1,
|
|
219
|
+
vector=[0.1, 0.2, 0.3, ...], # 384-dim vector
|
|
220
|
+
payload={"title": "Doc 1", "category": "tech"}
|
|
221
|
+
)
|
|
222
|
+
]
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
# Batch upsert
|
|
226
|
+
points = [
|
|
227
|
+
PointStruct(id=i, vector=vectors[i], payload=payloads[i])
|
|
228
|
+
for i in range(len(vectors))
|
|
229
|
+
]
|
|
230
|
+
client.upsert(collection_name="documents", points=points, batch_size=100)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Searching Vectors
|
|
234
|
+
```python
|
|
235
|
+
from qdrant_client.models import Filter, FieldCondition, MatchValue
|
|
236
|
+
|
|
237
|
+
# Basic search
|
|
238
|
+
results = client.search(
|
|
239
|
+
collection_name="documents",
|
|
240
|
+
query_vector=[0.1, 0.2, ...],
|
|
241
|
+
limit=10
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
# Search with filter
|
|
245
|
+
results = client.search(
|
|
246
|
+
collection_name="documents",
|
|
247
|
+
query_vector=[0.1, 0.2, ...],
|
|
248
|
+
query_filter=Filter(
|
|
249
|
+
must=[
|
|
250
|
+
FieldCondition(key="category", match=MatchValue(value="tech"))
|
|
251
|
+
]
|
|
252
|
+
),
|
|
253
|
+
limit=10,
|
|
254
|
+
with_payload=True,
|
|
255
|
+
score_threshold=0.7
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
# Search with range filter
|
|
259
|
+
from qdrant_client.models import Range
|
|
260
|
+
|
|
261
|
+
results = client.search(
|
|
262
|
+
collection_name="documents",
|
|
263
|
+
query_vector=query_vector,
|
|
264
|
+
query_filter=Filter(
|
|
265
|
+
must=[
|
|
266
|
+
FieldCondition(key="price", range=Range(gte=10, lte=100))
|
|
267
|
+
]
|
|
268
|
+
),
|
|
269
|
+
limit=10
|
|
270
|
+
)
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Payload Indexing
|
|
274
|
+
```python
|
|
275
|
+
# Create payload index for faster filtering
|
|
276
|
+
client.create_payload_index(
|
|
277
|
+
collection_name="documents",
|
|
278
|
+
field_name="category",
|
|
279
|
+
field_schema="keyword" # or "integer", "float", "bool"
|
|
280
|
+
)
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Best Practices
|
|
284
|
+
| Aspect | Recommendation |
|
|
285
|
+
|--------|----------------|
|
|
286
|
+
| Batch Size | 100-1000 points per upsert |
|
|
287
|
+
| Vector Dim | Match your embedding model (384, 768, 1536) |
|
|
288
|
+
| Filters | Index frequently filtered fields |
|
|
289
|
+
| Distance | COSINE for normalized, EUCLID for raw |
|
|
290
|
+
| Sharding | Use for >1M vectors |
|
|
291
|
+
|
|
292
|
+
### Distance Metrics
|
|
293
|
+
| Metric | Best For | Normalized |
|
|
294
|
+
|--------|----------|------------|
|
|
295
|
+
| COSINE | Text embeddings | Yes |
|
|
296
|
+
| EUCLID | Image embeddings | No |
|
|
297
|
+
| DOT | When vectors pre-normalized | Yes |
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: debug
|
|
3
|
+
description: "Debug errors and trace root causes systematically"
|
|
4
|
+
user-invocable: true
|
|
5
|
+
effort: medium
|
|
6
|
+
argument-hint: "[symptom]"
|
|
7
|
+
agent: debugger
|
|
8
|
+
context: fork
|
|
9
|
+
allowed-tools: Bash, Read, Grep
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Debug Helper
|
|
13
|
+
|
|
14
|
+
$ARGUMENTS
|
|
15
|
+
|
|
16
|
+
Systematic debugging for application issues.
|
|
17
|
+
|
|
18
|
+
## Project context
|
|
19
|
+
|
|
20
|
+
- Recent logs: !`docker compose logs --tail 20 2>/dev/null || tail -20 logs/*.log 2>/dev/null || echo "no-logs-found"`
|
|
21
|
+
|
|
22
|
+
## Automated Error Parsing
|
|
23
|
+
|
|
24
|
+
Pipe error output through the error parser for structured diagnosis:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Pipe from failing command
|
|
28
|
+
your_command 2>&1 | python3 "$(dirname "$0")/scripts/error-parser.py"
|
|
29
|
+
|
|
30
|
+
# Or from a log file
|
|
31
|
+
cat /var/log/app/error.log | python3 scripts/error-parser.py
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The script outputs JSON with:
|
|
35
|
+
- **language**: detected language (python/node/go/php)
|
|
36
|
+
- **error_type**: extracted error class (e.g., ModuleNotFoundError)
|
|
37
|
+
- **message**: the error message text
|
|
38
|
+
- **category**: classification (import, reference, type, connection, timeout, memory, permission, syntax)
|
|
39
|
+
- **stack_frames**: parsed file/line/function from the stack trace
|
|
40
|
+
- **files_to_check**: unique files from the trace, ordered by relevance
|
|
41
|
+
- **common_causes**: likely root causes for this error category
|
|
42
|
+
|
|
43
|
+
Use the parsed output to focus investigation on the right files and hypotheses.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Debugging Workflow
|
|
48
|
+
|
|
49
|
+
### 1. Check Logs
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Application logs (auto-detect environment)
|
|
53
|
+
# Docker:
|
|
54
|
+
docker compose logs --tail 100 {service} 2>&1 | grep -i error
|
|
55
|
+
|
|
56
|
+
# Bare metal / systemd:
|
|
57
|
+
journalctl -u {service} --since "1 hour ago" | grep -i error
|
|
58
|
+
|
|
59
|
+
# Log files:
|
|
60
|
+
tail -100 logs/app.log | grep -i error
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 2. Check Service Health
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Docker environment
|
|
67
|
+
docker compose ps
|
|
68
|
+
|
|
69
|
+
# Process check
|
|
70
|
+
ps aux | grep -E "(node|python|java|php)" | grep -v grep
|
|
71
|
+
|
|
72
|
+
# HTTP health endpoints
|
|
73
|
+
curl -sf http://localhost:{port}/health
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 3. Interactive Debug
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Python
|
|
80
|
+
python3 -c "import module; print(module.function('test'))"
|
|
81
|
+
|
|
82
|
+
# Node.js
|
|
83
|
+
node -e "const m = require('./module'); console.log(m.fn('test'))"
|
|
84
|
+
|
|
85
|
+
# PHP
|
|
86
|
+
php -r "require 'vendor/autoload.php'; echo MyClass::method('test');"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 4. Database Checks
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# PostgreSQL
|
|
93
|
+
psql -U postgres -c "SELECT version();"
|
|
94
|
+
|
|
95
|
+
# MySQL
|
|
96
|
+
mysql -e "SELECT VERSION();"
|
|
97
|
+
|
|
98
|
+
# Redis
|
|
99
|
+
redis-cli ping && redis-cli info memory
|
|
100
|
+
|
|
101
|
+
# MongoDB
|
|
102
|
+
mongosh --eval "db.runCommand({ping:1})"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Common Debug Scenarios
|
|
106
|
+
|
|
107
|
+
### API Returns 500
|
|
108
|
+
```bash
|
|
109
|
+
# Check server logs for stack traces
|
|
110
|
+
grep -A5 "Traceback\|Error\|Exception" logs/app.log
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Slow Performance
|
|
114
|
+
```bash
|
|
115
|
+
# Resource usage
|
|
116
|
+
top -bn1 | head -20 # CPU/memory
|
|
117
|
+
iostat -x 1 3 # Disk I/O
|
|
118
|
+
ss -tlnp # Open connections
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Connection Issues
|
|
122
|
+
```bash
|
|
123
|
+
# Test connectivity
|
|
124
|
+
curl -I http://localhost:{port}
|
|
125
|
+
nc -zv {host} {port}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Parallel Hypothesis Debugging (Agent Teams)
|
|
129
|
+
|
|
130
|
+
For complex bugs (open >1h, unclear root cause), spawn teammates to investigate competing hypotheses:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
Create an agent team to debug this issue:
|
|
134
|
+
- Teammate 1 (debugger): "Investigate if [bug] is caused by [hypothesis A: database issue].
|
|
135
|
+
Check logs, connection pools, timeouts, query performance."
|
|
136
|
+
Use Opus.
|
|
137
|
+
- Teammate 2 (debugger): "Investigate if [bug] is caused by [hypothesis B: race condition].
|
|
138
|
+
Look for async issues, locking, concurrency, shared state."
|
|
139
|
+
Use Opus.
|
|
140
|
+
- Teammate 3 (debugger): "Investigate if [bug] is caused by [hypothesis C: configuration drift].
|
|
141
|
+
Compare env vars, config files, recent changes, dependency versions."
|
|
142
|
+
Use Opus.
|
|
143
|
+
Have them talk to each other to challenge each other's theories.
|
|
144
|
+
Report consensus when done.
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Debug Checklist
|
|
148
|
+
|
|
149
|
+
- [ ] Identified error/symptom
|
|
150
|
+
- [ ] Checked relevant logs
|
|
151
|
+
- [ ] Verified service health
|
|
152
|
+
- [ ] Reproduced issue
|
|
153
|
+
- [ ] Formed hypothesis
|
|
154
|
+
- [ ] Tested fix
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Parse error messages and stack traces from stdin for structured diagnosis.
|
|
3
|
+
|
|
4
|
+
Reads raw error output piped from a failing command or log file,
|
|
5
|
+
detects the programming language (Python, Node.js, Go, PHP), extracts
|
|
6
|
+
the error type, message, and stack frames, classifies the error into a
|
|
7
|
+
category, and outputs a JSON object with common causes and files to
|
|
8
|
+
investigate.
|
|
9
|
+
|
|
10
|
+
Usage::
|
|
11
|
+
|
|
12
|
+
your_command 2>&1 | python3 error-parser.py
|
|
13
|
+
cat /var/log/app/error.log | python3 error-parser.py
|
|
14
|
+
"""
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import json
|
|
18
|
+
import re
|
|
19
|
+
import sys
|
|
20
|
+
from typing import Any
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
LANGUAGE_SIGNATURES: dict[str, list[str]] = {
|
|
24
|
+
"python": [r"Traceback \(most recent call last\)", r"File \".*\", line \d+"],
|
|
25
|
+
"node": [r"at Object\.<anonymous>", r"at Module\.", r"node:internal", r"at .*\(.*\.js:\d+:\d+\)"],
|
|
26
|
+
"go": [r"goroutine \d+", r"panic:", r"\.go:\d+"],
|
|
27
|
+
"php": [r"Fatal error:", r"PHP (?:Warning|Notice|Fatal)", r"Stack trace:", r"\.php:\d+"],
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
ERROR_CATEGORIES: dict[str, list[str]] = {
|
|
31
|
+
"import": [r"ModuleNotFoundError", r"ImportError", r"Cannot find module", r"no required module", r"undefined: "],
|
|
32
|
+
"reference": [r"NameError", r"ReferenceError", r"undefined variable", r"Undefined variable"],
|
|
33
|
+
"type": [r"TypeError", r"type mismatch", r"cannot use .* as type"],
|
|
34
|
+
"connection": [r"ConnectionRefusedError", r"ECONNREFUSED", r"connection refused", r"dial tcp"],
|
|
35
|
+
"timeout": [r"TimeoutError", r"ETIMEDOUT", r"context deadline exceeded", r"Maximum execution time"],
|
|
36
|
+
"memory": [r"MemoryError", r"heap out of memory", r"out of memory", r"Allowed memory size"],
|
|
37
|
+
"permission": [r"PermissionError", r"EACCES", r"permission denied", r"Access denied"],
|
|
38
|
+
"syntax": [r"SyntaxError", r"Unexpected token", r"syntax error", r"Parse error"],
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
COMMON_CAUSES: dict[str, list[str]] = {
|
|
42
|
+
"import": ["Missing dependency (run pip install / npm install)", "Typo in module name", "Virtual environment not activated"],
|
|
43
|
+
"reference": ["Variable used before assignment", "Typo in variable/function name", "Missing import"],
|
|
44
|
+
"type": ["Wrong argument type passed", "None/null not handled", "API response shape changed"],
|
|
45
|
+
"connection": ["Service not running", "Wrong host/port", "Firewall blocking connection"],
|
|
46
|
+
"timeout": ["Service overloaded", "Network latency", "Query too slow - add index"],
|
|
47
|
+
"memory": ["Large dataset loaded into memory", "Memory leak in loop", "Increase memory limit"],
|
|
48
|
+
"permission": ["File ownership issue", "Missing sudo/elevation", "SELinux/AppArmor policy"],
|
|
49
|
+
"syntax": ["Missing bracket/parenthesis", "Invalid JSON/YAML", "Wrong language version"],
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def detect_language(text: str) -> str:
|
|
54
|
+
"""Detect the programming language from characteristic error patterns.
|
|
55
|
+
|
|
56
|
+
Scores each supported language by counting how many of its
|
|
57
|
+
signature patterns match the input text and returns the language
|
|
58
|
+
with the highest score.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
text: Raw error output text.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
Detected language name or ``"unknown"``.
|
|
65
|
+
"""
|
|
66
|
+
scores: dict[str, int] = {}
|
|
67
|
+
for lang, patterns in LANGUAGE_SIGNATURES.items():
|
|
68
|
+
score = sum(1 for p in patterns if re.search(p, text))
|
|
69
|
+
if score > 0:
|
|
70
|
+
scores[lang] = score
|
|
71
|
+
if not scores:
|
|
72
|
+
return "unknown"
|
|
73
|
+
return max(scores, key=scores.get)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def categorize_error(text: str) -> str:
|
|
77
|
+
"""Categorize error text into a high-level domain.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
text: Raw error output text.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Category string (e.g. ``"import"``, ``"connection"``) or
|
|
84
|
+
``"unknown"``.
|
|
85
|
+
"""
|
|
86
|
+
for category, patterns in ERROR_CATEGORIES.items():
|
|
87
|
+
for p in patterns:
|
|
88
|
+
if re.search(p, text, re.IGNORECASE):
|
|
89
|
+
return category
|
|
90
|
+
return "unknown"
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def extract_frames(text: str, language: str) -> list[dict[str, Any]]:
|
|
94
|
+
"""Extract stack trace frames based on the detected language.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
text: Raw error output text.
|
|
98
|
+
language: Detected language (``"python"``, ``"node"``, ``"go"``,
|
|
99
|
+
``"php"``).
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
List of frame dictionaries with ``file``, ``line``, and
|
|
103
|
+
``function`` keys.
|
|
104
|
+
"""
|
|
105
|
+
frames: list[dict[str, Any]] = []
|
|
106
|
+
if language == "python":
|
|
107
|
+
for m in re.finditer(r'File "([^"]+)", line (\d+)(?:, in (.+))?', text):
|
|
108
|
+
frames.append({"file": m.group(1), "line": int(m.group(2)), "function": m.group(3) or ""})
|
|
109
|
+
elif language == "node":
|
|
110
|
+
for m in re.finditer(r"at (?:(.+?) \()?(.+?):(\d+):(\d+)\)?", text):
|
|
111
|
+
frames.append({"file": m.group(2), "line": int(m.group(3)), "function": m.group(1) or ""})
|
|
112
|
+
elif language == "go":
|
|
113
|
+
for m in re.finditer(r"(\S+\.go):(\d+)", text):
|
|
114
|
+
frames.append({"file": m.group(1), "line": int(m.group(2)), "function": ""})
|
|
115
|
+
elif language == "php":
|
|
116
|
+
for m in re.finditer(r"(?:#\d+\s+)?(\S+\.php)(?:\((\d+)\))?(?::\s*(.+))?", text):
|
|
117
|
+
frames.append({"file": m.group(1), "line": int(m.group(2)) if m.group(2) else 0, "function": m.group(3) or ""})
|
|
118
|
+
return frames
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def extract_error_message(text: str, language: str) -> tuple[str, str]:
|
|
122
|
+
"""Extract the primary error type and message from error output.
|
|
123
|
+
|
|
124
|
+
Uses language-specific regex patterns to find the error class and
|
|
125
|
+
description. Falls back to searching for lines containing common
|
|
126
|
+
error keywords.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
text: Raw error output text.
|
|
130
|
+
language: Detected language identifier.
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
A ``(error_type, message)`` tuple.
|
|
134
|
+
"""
|
|
135
|
+
patterns: dict[str, str] = {
|
|
136
|
+
"python": r"(\w+Error|\w+Exception|\w+Warning):\s*(.+)",
|
|
137
|
+
"node": r"(\w+Error|\w+Exception):\s*(.+)",
|
|
138
|
+
"go": r"(?:panic:\s*(.+)|fatal error:\s*(.+))",
|
|
139
|
+
"php": r"(?:Fatal error|PHP \w+):\s*(.+?)(?:\s+in\s+|$)",
|
|
140
|
+
}
|
|
141
|
+
pattern = patterns.get(language, r"(\w+Error|\w+Exception):\s*(.+)")
|
|
142
|
+
m = re.search(pattern, text)
|
|
143
|
+
if m:
|
|
144
|
+
groups = [g for g in m.groups() if g]
|
|
145
|
+
if len(groups) >= 2:
|
|
146
|
+
return groups[0], groups[1].strip()
|
|
147
|
+
elif groups:
|
|
148
|
+
return "Error", groups[0].strip()
|
|
149
|
+
# Fallback: first non-empty line that looks like an error
|
|
150
|
+
for line in text.split("\n"):
|
|
151
|
+
line = line.strip()
|
|
152
|
+
if line and any(kw in line.lower() for kw in ["error", "exception", "fatal", "panic"]):
|
|
153
|
+
return "Error", line[:200]
|
|
154
|
+
return "Unknown", "Could not parse error message"
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def main() -> None:
|
|
158
|
+
"""Entry point: read stdin, parse errors, and print JSON to stdout."""
|
|
159
|
+
text = sys.stdin.read()
|
|
160
|
+
if not text.strip():
|
|
161
|
+
print(json.dumps({"error": "No input provided. Pipe error output to stdin."}))
|
|
162
|
+
return
|
|
163
|
+
|
|
164
|
+
language = detect_language(text)
|
|
165
|
+
error_type, message = extract_error_message(text, language)
|
|
166
|
+
category = categorize_error(text)
|
|
167
|
+
frames = extract_frames(text, language)
|
|
168
|
+
causes = COMMON_CAUSES.get(category, ["Unknown error category - manual investigation required"])
|
|
169
|
+
|
|
170
|
+
# Files to check - unique files from stack frames
|
|
171
|
+
files_to_check = list(dict.fromkeys(f["file"] for f in frames if f["file"]))[:10]
|
|
172
|
+
|
|
173
|
+
result: dict[str, Any] = {
|
|
174
|
+
"language": language,
|
|
175
|
+
"error_type": error_type,
|
|
176
|
+
"message": message,
|
|
177
|
+
"category": category,
|
|
178
|
+
"stack_frames": frames[:20],
|
|
179
|
+
"files_to_check": files_to_check,
|
|
180
|
+
"common_causes": causes,
|
|
181
|
+
"raw_lines": len(text.split("\n")),
|
|
182
|
+
}
|
|
183
|
+
print(json.dumps(result, indent=2))
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
if __name__ == "__main__":
|
|
187
|
+
main()
|