@fro.bot/systematic 2.33.2 → 3.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/ATTRIBUTIONS.md +1 -1
- package/agents/design/design-iterator.md +1 -0
- package/agents/research/best-practices-researcher.md +6 -8
- package/agents/review/pattern-recognition-specialist.md +1 -1
- package/agents/workflow/systematic-implementer.md +1 -0
- package/dist/cli.js +348 -53
- package/dist/{index-vyzhzvap.js → index-yskzf7vh.js} +587 -386
- package/dist/index.js +100 -155
- package/dist/lib/agent-overlays.d.ts +0 -1
- package/dist/lib/agent-resolver.d.ts +28 -0
- package/dist/lib/bootstrap.d.ts +8 -1
- package/dist/lib/bundled-names.d.ts +3 -3
- package/dist/lib/pi-delegate-session.d.ts +31 -0
- package/dist/lib/pi-delegate-tool.d.ts +42 -0
- package/dist/lib/removed-names.d.ts +3 -3
- package/dist/lib/setup.d.ts +36 -0
- package/dist/lib/skill-loader.d.ts +1 -2
- package/dist/lib/skill-resolver.d.ts +39 -0
- package/dist/lib/skill-tool.d.ts +2 -11
- package/dist/lib/skills.d.ts +1 -9
- package/dist/lib/source-model-defaults.d.ts +1 -1
- package/dist/pi.d.ts +7 -0
- package/dist/pi.js +3641 -0
- package/dist/schemas/systematic-config.schema.json +47 -242
- package/package.json +31 -8
- package/skills/ce-brainstorm/references/handoff.md +5 -26
- package/skills/ce-brainstorm/references/universal-brainstorming.md +0 -1
- package/skills/ce-compound/SKILL.md +8 -12
- package/skills/ce-ideate/references/post-ideation-workflow.md +21 -85
- package/skills/ce-plan/SKILL.md +6 -6
- package/skills/ce-plan/references/deepening-workflow.md +6 -7
- package/skills/ce-plan/references/plan-handoff.md +1 -17
- package/skills/ce-plan/references/universal-planning.md +0 -4
- package/skills/ce-review/SKILL.md +10 -19
- package/skills/ce-review/references/persona-catalog.md +2 -7
- package/skills/ce-review/references/review-output-template.md +0 -1
- package/skills/ce-work/SKILL.md +1 -1
- package/skills/deepen-plan/SKILL.md +6 -7
- package/skills/document-review/SKILL.md +2 -2
- package/skills/git-commit-push-pr/SKILL.md +1 -2
- package/skills/lfg/SKILL.md +1 -1
- package/skills/onboarding/SKILL.md +1 -12
- package/skills/orchestrating-subagents/SKILL.md +2 -2
- package/skills/slfg/SKILL.md +2 -3
- package/skills/test-browser/SKILL.md +2 -2
- package/skills/todos/SKILL.md +239 -0
- package/skills/writing-skills/SKILL.md +102 -1
- package/skills/{writing-systematic-skills → writing-skills}/references/foundation-conventions.md +5 -5
- package/agents/design/design-implementation-reviewer.md +0 -95
- package/agents/design/figma-design-sync.md +0 -173
- package/agents/docs/ankane-readme-writer.md +0 -51
- package/agents/review/cli-agent-readiness-reviewer.md +0 -418
- package/agents/review/data-integrity-guardian.md +0 -72
- package/agents/review/data-migration-expert.md +0 -99
- package/agents/review/dhh-rails-reviewer.md +0 -46
- package/agents/review/julik-frontend-races-reviewer.md +0 -49
- package/agents/review/kieran-python-reviewer.md +0 -47
- package/agents/review/kieran-rails-reviewer.md +0 -47
- package/agents/review/performance-oracle.md +0 -112
- package/agents/review/schema-drift-detector.md +0 -143
- package/agents/review/security-sentinel.md +0 -95
- package/agents/workflow/lint.md +0 -17
- package/dist/lib/converter.d.ts +0 -14
- package/skills/andrew-kane-gem-writer/SKILL.md +0 -184
- package/skills/andrew-kane-gem-writer/references/database-adapters.md +0 -231
- package/skills/andrew-kane-gem-writer/references/module-organization.md +0 -121
- package/skills/andrew-kane-gem-writer/references/rails-integration.md +0 -183
- package/skills/andrew-kane-gem-writer/references/resources.md +0 -119
- package/skills/andrew-kane-gem-writer/references/testing-patterns.md +0 -261
- package/skills/changelog/SKILL.md +0 -139
- package/skills/claude-permissions-optimizer/SKILL.md +0 -166
- package/skills/claude-permissions-optimizer/scripts/extract-commands.mjs +0 -655
- package/skills/claude-permissions-optimizer/scripts/normalize.mjs +0 -151
- package/skills/dhh-rails-style/SKILL.md +0 -186
- package/skills/dhh-rails-style/references/architecture.md +0 -653
- package/skills/dhh-rails-style/references/controllers.md +0 -303
- package/skills/dhh-rails-style/references/frontend.md +0 -510
- package/skills/dhh-rails-style/references/gems.md +0 -266
- package/skills/dhh-rails-style/references/models.md +0 -359
- package/skills/dhh-rails-style/references/testing.md +0 -338
- package/skills/dspy-ruby/SKILL.md +0 -737
- package/skills/dspy-ruby/assets/config-template.rb +0 -187
- package/skills/dspy-ruby/assets/module-template.rb +0 -300
- package/skills/dspy-ruby/assets/signature-template.rb +0 -221
- package/skills/dspy-ruby/references/core-concepts.md +0 -674
- package/skills/dspy-ruby/references/observability.md +0 -366
- package/skills/dspy-ruby/references/optimization.md +0 -603
- package/skills/dspy-ruby/references/providers.md +0 -418
- package/skills/dspy-ruby/references/toolsets.md +0 -502
- package/skills/every-style-editor/SKILL.md +0 -135
- package/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +0 -529
- package/skills/feature-video/SKILL.md +0 -383
- package/skills/gemini-imagegen/SKILL.md +0 -237
- package/skills/gemini-imagegen/requirements.txt +0 -2
- package/skills/gemini-imagegen/scripts/compose_images.py +0 -157
- package/skills/gemini-imagegen/scripts/edit_image.py +0 -144
- package/skills/gemini-imagegen/scripts/gemini_images.py +0 -263
- package/skills/gemini-imagegen/scripts/generate_image.py +0 -133
- package/skills/gemini-imagegen/scripts/multi_turn_chat.py +0 -216
- package/skills/generate_command/SKILL.md +0 -164
- package/skills/orchestrating-swarms/SKILL.md +0 -1723
- package/skills/proof/SKILL.md +0 -291
- package/skills/proof/references/hitl-review.md +0 -368
- package/skills/rclone/SKILL.md +0 -150
- package/skills/rclone/scripts/check_setup.sh +0 -60
- package/skills/setup/SKILL.md +0 -22
- package/skills/test-xcode/SKILL.md +0 -214
- package/skills/todo-create/SKILL.md +0 -109
- package/skills/todo-resolve/SKILL.md +0 -68
- package/skills/todo-triage/SKILL.md +0 -70
- package/skills/writing-systematic-skills/SKILL.md +0 -119
- /package/skills/{todo-create → todos}/assets/todo-template.md +0 -0
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: security-sentinel
|
|
3
|
-
description: "Performs security audits for vulnerabilities, input validation, auth/authz, hardcoded secrets, and OWASP compliance. Use when reviewing code for security issues or before deployment."
|
|
4
|
-
tools: Read, Grep, Glob, Bash
|
|
5
|
-
mode: subagent
|
|
6
|
-
temperature: 0.1
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
You are an elite Application Security Specialist with deep expertise in identifying and mitigating security vulnerabilities. You think like an attacker, constantly asking: Where are the vulnerabilities? What could go wrong? How could this be exploited?
|
|
10
|
-
|
|
11
|
-
Your mission is to perform comprehensive security audits with laser focus on finding and reporting vulnerabilities before they can be exploited.
|
|
12
|
-
|
|
13
|
-
## Core Security Scanning Protocol
|
|
14
|
-
|
|
15
|
-
You will systematically execute these security scans:
|
|
16
|
-
|
|
17
|
-
1. **Input Validation Analysis**
|
|
18
|
-
- Search for all input points: `grep -r "req\.\(body\|params\|query\)" --include="*.js"`
|
|
19
|
-
- For Rails projects: `grep -r "params\[" --include="*.rb"`
|
|
20
|
-
- Verify each input is properly validated and sanitized
|
|
21
|
-
- Check for type validation, length limits, and format constraints
|
|
22
|
-
|
|
23
|
-
2. **SQL Injection Risk Assessment**
|
|
24
|
-
- Scan for raw queries: `grep -r "query\|execute" --include="*.js" | grep -v "?"`
|
|
25
|
-
- For Rails: Check for raw SQL in models and controllers
|
|
26
|
-
- Ensure all queries use parameterization or prepared statements
|
|
27
|
-
- Flag any string concatenation in SQL contexts
|
|
28
|
-
|
|
29
|
-
3. **XSS Vulnerability Detection**
|
|
30
|
-
- Identify all output points in views and templates
|
|
31
|
-
- Check for proper escaping of user-generated content
|
|
32
|
-
- Verify Content Security Policy headers
|
|
33
|
-
- Look for dangerous innerHTML or dangerouslySetInnerHTML usage
|
|
34
|
-
|
|
35
|
-
4. **Authentication & Authorization Audit**
|
|
36
|
-
- Map all endpoints and verify authentication requirements
|
|
37
|
-
- Check for proper session management
|
|
38
|
-
- Verify authorization checks at both route and resource levels
|
|
39
|
-
- Look for privilege escalation possibilities
|
|
40
|
-
|
|
41
|
-
5. **Sensitive Data Exposure**
|
|
42
|
-
- Execute: `grep -r "password\|secret\|key\|token" --include="*.js"`
|
|
43
|
-
- Scan for hardcoded credentials, API keys, or secrets
|
|
44
|
-
- Check for sensitive data in logs or error messages
|
|
45
|
-
- Verify proper encryption for sensitive data at rest and in transit
|
|
46
|
-
|
|
47
|
-
6. **OWASP Top 10 Compliance**
|
|
48
|
-
- Systematically check against each OWASP Top 10 vulnerability
|
|
49
|
-
- Document compliance status for each category
|
|
50
|
-
- Provide specific remediation steps for any gaps
|
|
51
|
-
|
|
52
|
-
## Security Requirements Checklist
|
|
53
|
-
|
|
54
|
-
For every review, you will verify:
|
|
55
|
-
|
|
56
|
-
- [ ] All inputs validated and sanitized
|
|
57
|
-
- [ ] No hardcoded secrets or credentials
|
|
58
|
-
- [ ] Proper authentication on all endpoints
|
|
59
|
-
- [ ] SQL queries use parameterization
|
|
60
|
-
- [ ] XSS protection implemented
|
|
61
|
-
- [ ] HTTPS enforced where needed
|
|
62
|
-
- [ ] CSRF protection enabled
|
|
63
|
-
- [ ] Security headers properly configured
|
|
64
|
-
- [ ] Error messages don't leak sensitive information
|
|
65
|
-
- [ ] Dependencies are up-to-date and vulnerability-free
|
|
66
|
-
|
|
67
|
-
## Reporting Protocol
|
|
68
|
-
|
|
69
|
-
Your security reports will include:
|
|
70
|
-
|
|
71
|
-
1. **Executive Summary**: High-level risk assessment with severity ratings
|
|
72
|
-
2. **Detailed Findings**: For each vulnerability:
|
|
73
|
-
- Description of the issue
|
|
74
|
-
- Potential impact and exploitability
|
|
75
|
-
- Specific code location
|
|
76
|
-
- Proof of concept (if applicable)
|
|
77
|
-
- Remediation recommendations
|
|
78
|
-
3. **Risk Matrix**: Categorize findings by severity (Critical, High, Medium, Low)
|
|
79
|
-
4. **Remediation Roadmap**: Prioritized action items with implementation guidance
|
|
80
|
-
|
|
81
|
-
## Operational Guidelines
|
|
82
|
-
|
|
83
|
-
- Always assume the worst-case scenario
|
|
84
|
-
- Test edge cases and unexpected inputs
|
|
85
|
-
- Consider both external and internal threat actors
|
|
86
|
-
- Don't just find problems—provide actionable solutions
|
|
87
|
-
- Use automated tools but verify findings manually
|
|
88
|
-
- Stay current with latest attack vectors and security best practices
|
|
89
|
-
- When reviewing Rails applications, pay special attention to:
|
|
90
|
-
- Strong parameters usage
|
|
91
|
-
- CSRF token implementation
|
|
92
|
-
- Mass assignment vulnerabilities
|
|
93
|
-
- Unsafe redirects
|
|
94
|
-
|
|
95
|
-
You are the last line of defense. Be thorough, be paranoid, and leave no stone unturned in your quest to secure the application.
|
package/agents/workflow/lint.md
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: lint
|
|
3
|
-
description: Use this agent when you need to run linting and code quality checks on Ruby and ERB files. Run before pushing to origin.
|
|
4
|
-
color: warning
|
|
5
|
-
mode: subagent
|
|
6
|
-
temperature: 0.1
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
Your workflow process:
|
|
10
|
-
|
|
11
|
-
1. **Initial Assessment**: Determine which checks are needed based on the files changed or the specific request
|
|
12
|
-
2. **Execute Appropriate Tools**:
|
|
13
|
-
- For Ruby files: `bundle exec standardrb` for checking, `bundle exec standardrb --fix` for auto-fixing
|
|
14
|
-
- For ERB templates: `bundle exec erblint --lint-all` for checking, `bundle exec erblint --lint-all --autocorrect` for auto-fixing
|
|
15
|
-
- For security: `bin/brakeman` for vulnerability scanning
|
|
16
|
-
3. **Analyze Results**: Parse tool outputs to identify patterns and prioritize issues
|
|
17
|
-
4. **Take Action**: Commit fixes with `style: linting`
|
package/dist/lib/converter.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { type AgentMode } from './validation.js';
|
|
2
|
-
export type ContentType = 'skill' | 'agent' | 'command';
|
|
3
|
-
export type SourceType = 'bundled' | 'external';
|
|
4
|
-
export interface ConvertOptions {
|
|
5
|
-
source?: SourceType;
|
|
6
|
-
agentMode?: AgentMode;
|
|
7
|
-
/** Skip body content transformations (tool names, paths, etc.) */
|
|
8
|
-
skipBodyTransform?: boolean;
|
|
9
|
-
}
|
|
10
|
-
export declare const CONVERTER_VERSION = 2;
|
|
11
|
-
export declare const TOOL_NAME_MAP: Record<string, string>;
|
|
12
|
-
export declare function convertContent(content: string, type: ContentType, options?: ConvertOptions): string;
|
|
13
|
-
export declare function convertFileWithCache(filePath: string, type: ContentType, options?: ConvertOptions): string;
|
|
14
|
-
export declare function clearConverterCache(): void;
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: andrew-kane-gem-writer
|
|
3
|
-
description: This skill should be used when writing Ruby gems following Andrew Kane's proven patterns and philosophy. It applies when creating new Ruby gems, refactoring existing gems, designing gem APIs, or when clean, minimal, production-ready Ruby library code is needed. Triggers on requests like "create a gem", "write a Ruby library", "design a gem API", or mentions of Andrew Kane's style.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Andrew Kane Gem Writer
|
|
7
|
-
|
|
8
|
-
Write Ruby gems following Andrew Kane's battle-tested patterns from 100+ gems with 374M+ downloads (Searchkick, PgHero, Chartkick, Strong Migrations, Lockbox, Ahoy, Blazer, Groupdate, Neighbor, Blind Index).
|
|
9
|
-
|
|
10
|
-
## Core Philosophy
|
|
11
|
-
|
|
12
|
-
**Simplicity over cleverness.** Zero or minimal dependencies. Explicit code over metaprogramming. Rails integration without Rails coupling. Every pattern serves production use cases.
|
|
13
|
-
|
|
14
|
-
## Entry Point Structure
|
|
15
|
-
|
|
16
|
-
Every gem follows this exact pattern in `lib/gemname.rb`:
|
|
17
|
-
|
|
18
|
-
```ruby
|
|
19
|
-
# 1. Dependencies (stdlib preferred)
|
|
20
|
-
require "forwardable"
|
|
21
|
-
|
|
22
|
-
# 2. Internal modules
|
|
23
|
-
require_relative "gemname/model"
|
|
24
|
-
require_relative "gemname/version"
|
|
25
|
-
|
|
26
|
-
# 3. Conditional Rails (CRITICAL - never require Rails directly)
|
|
27
|
-
require_relative "gemname/railtie" if defined?(Rails)
|
|
28
|
-
|
|
29
|
-
# 4. Module with config and errors
|
|
30
|
-
module GemName
|
|
31
|
-
class Error < StandardError; end
|
|
32
|
-
class InvalidConfigError < Error; end
|
|
33
|
-
|
|
34
|
-
class << self
|
|
35
|
-
attr_accessor :timeout, :logger
|
|
36
|
-
attr_writer :client
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
self.timeout = 10 # Defaults set immediately
|
|
40
|
-
end
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Class Macro DSL Pattern
|
|
44
|
-
|
|
45
|
-
The signature Kane pattern—single method call configures everything:
|
|
46
|
-
|
|
47
|
-
```ruby
|
|
48
|
-
# Usage
|
|
49
|
-
class Product < ApplicationRecord
|
|
50
|
-
searchkick word_start: [:name]
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# Implementation
|
|
54
|
-
module GemName
|
|
55
|
-
module Model
|
|
56
|
-
def gemname(**options)
|
|
57
|
-
unknown = options.keys - KNOWN_KEYWORDS
|
|
58
|
-
raise ArgumentError, "unknown keywords: #{unknown.join(", ")}" if unknown.any?
|
|
59
|
-
|
|
60
|
-
mod = Module.new
|
|
61
|
-
mod.module_eval do
|
|
62
|
-
define_method :some_method do
|
|
63
|
-
# implementation
|
|
64
|
-
end unless method_defined?(:some_method)
|
|
65
|
-
end
|
|
66
|
-
include mod
|
|
67
|
-
|
|
68
|
-
class_eval do
|
|
69
|
-
cattr_reader :gemname_options, instance_reader: false
|
|
70
|
-
class_variable_set :@@gemname_options, options.dup
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## Rails Integration
|
|
78
|
-
|
|
79
|
-
**Always use `ActiveSupport.on_load`—never require Rails gems directly:**
|
|
80
|
-
|
|
81
|
-
```ruby
|
|
82
|
-
# WRONG
|
|
83
|
-
require "active_record"
|
|
84
|
-
ActiveRecord::Base.include(MyGem::Model)
|
|
85
|
-
|
|
86
|
-
# CORRECT
|
|
87
|
-
ActiveSupport.on_load(:active_record) do
|
|
88
|
-
extend GemName::Model
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# Use prepend for behavior modification
|
|
92
|
-
ActiveSupport.on_load(:active_record) do
|
|
93
|
-
ActiveRecord::Migration.prepend(GemName::Migration)
|
|
94
|
-
end
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## Configuration Pattern
|
|
98
|
-
|
|
99
|
-
Use `class << self` with `attr_accessor`, not Configuration objects:
|
|
100
|
-
|
|
101
|
-
```ruby
|
|
102
|
-
module GemName
|
|
103
|
-
class << self
|
|
104
|
-
attr_accessor :timeout, :logger
|
|
105
|
-
attr_writer :master_key
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
def self.master_key
|
|
109
|
-
@master_key ||= ENV["GEMNAME_MASTER_KEY"]
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
self.timeout = 10
|
|
113
|
-
self.logger = nil
|
|
114
|
-
end
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
## Error Handling
|
|
118
|
-
|
|
119
|
-
Simple hierarchy with informative messages:
|
|
120
|
-
|
|
121
|
-
```ruby
|
|
122
|
-
module GemName
|
|
123
|
-
class Error < StandardError; end
|
|
124
|
-
class ConfigError < Error; end
|
|
125
|
-
class ValidationError < Error; end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
# Validate early with ArgumentError
|
|
129
|
-
def initialize(key:)
|
|
130
|
-
raise ArgumentError, "Key must be 32 bytes" unless key&.bytesize == 32
|
|
131
|
-
end
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
## Testing (Minitest Only)
|
|
135
|
-
|
|
136
|
-
```ruby
|
|
137
|
-
# test/test_helper.rb
|
|
138
|
-
require "bundler/setup"
|
|
139
|
-
Bundler.require(:default)
|
|
140
|
-
require "minitest/autorun"
|
|
141
|
-
require "minitest/pride"
|
|
142
|
-
|
|
143
|
-
# test/model_test.rb
|
|
144
|
-
class ModelTest < Minitest::Test
|
|
145
|
-
def test_basic_functionality
|
|
146
|
-
assert_equal expected, actual
|
|
147
|
-
end
|
|
148
|
-
end
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
## Gemspec Pattern
|
|
152
|
-
|
|
153
|
-
Zero runtime dependencies when possible:
|
|
154
|
-
|
|
155
|
-
```ruby
|
|
156
|
-
Gem::Specification.new do |spec|
|
|
157
|
-
spec.name = "gemname"
|
|
158
|
-
spec.version = GemName::VERSION
|
|
159
|
-
spec.required_ruby_version = ">= 3.1"
|
|
160
|
-
spec.files = Dir["*.{md,txt}", "{lib}/**/*"]
|
|
161
|
-
spec.require_path = "lib"
|
|
162
|
-
# NO add_dependency lines - dev deps go in Gemfile
|
|
163
|
-
end
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
## Anti-Patterns to Avoid
|
|
167
|
-
|
|
168
|
-
- `method_missing` (use `define_method` instead)
|
|
169
|
-
- Configuration objects (use class accessors)
|
|
170
|
-
- `@@class_variables` (use `class << self`)
|
|
171
|
-
- Requiring Rails gems directly
|
|
172
|
-
- Many runtime dependencies
|
|
173
|
-
- Committing Gemfile.lock in gems
|
|
174
|
-
- RSpec (use Minitest)
|
|
175
|
-
- Heavy DSLs (prefer explicit Ruby)
|
|
176
|
-
|
|
177
|
-
## Reference Files
|
|
178
|
-
|
|
179
|
-
For deeper patterns, see:
|
|
180
|
-
- `references/module-organization.md` - Directory layouts, method decomposition
|
|
181
|
-
- `references/rails-integration.md` - Railtie, Engine, on_load patterns
|
|
182
|
-
- `references/database-adapters.md` - Multi-database support patterns
|
|
183
|
-
- `references/testing-patterns.md` - Multi-version testing, CI setup
|
|
184
|
-
- `references/resources.md` - Links to Kane's repos and articles
|
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
# Database Adapter Patterns
|
|
2
|
-
|
|
3
|
-
## Abstract Base Class Pattern
|
|
4
|
-
|
|
5
|
-
```ruby
|
|
6
|
-
# lib/strong_migrations/adapters/abstract_adapter.rb
|
|
7
|
-
module StrongMigrations
|
|
8
|
-
module Adapters
|
|
9
|
-
class AbstractAdapter
|
|
10
|
-
def initialize(checker)
|
|
11
|
-
@checker = checker
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def min_version
|
|
15
|
-
nil
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def set_statement_timeout(timeout)
|
|
19
|
-
# no-op by default
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def check_lock_timeout
|
|
23
|
-
# no-op by default
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
private
|
|
27
|
-
|
|
28
|
-
def connection
|
|
29
|
-
@checker.send(:connection)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def quote(value)
|
|
33
|
-
connection.quote(value)
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## PostgreSQL Adapter
|
|
41
|
-
|
|
42
|
-
```ruby
|
|
43
|
-
# lib/strong_migrations/adapters/postgresql_adapter.rb
|
|
44
|
-
module StrongMigrations
|
|
45
|
-
module Adapters
|
|
46
|
-
class PostgreSQLAdapter < AbstractAdapter
|
|
47
|
-
def min_version
|
|
48
|
-
"12"
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def set_statement_timeout(timeout)
|
|
52
|
-
select_all("SET statement_timeout = #{timeout.to_i * 1000}")
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def set_lock_timeout(timeout)
|
|
56
|
-
select_all("SET lock_timeout = #{timeout.to_i * 1000}")
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def check_lock_timeout
|
|
60
|
-
lock_timeout = connection.select_value("SHOW lock_timeout")
|
|
61
|
-
lock_timeout_sec = timeout_to_sec(lock_timeout)
|
|
62
|
-
# validation logic
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
private
|
|
66
|
-
|
|
67
|
-
def select_all(sql)
|
|
68
|
-
connection.select_all(sql)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def timeout_to_sec(timeout)
|
|
72
|
-
units = {"us" => 1e-6, "ms" => 1e-3, "s" => 1, "min" => 60}
|
|
73
|
-
timeout.to_f * (units[timeout.gsub(/\d+/, "")] || 1e-3)
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
## MySQL Adapter
|
|
81
|
-
|
|
82
|
-
```ruby
|
|
83
|
-
# lib/strong_migrations/adapters/mysql_adapter.rb
|
|
84
|
-
module StrongMigrations
|
|
85
|
-
module Adapters
|
|
86
|
-
class MySQLAdapter < AbstractAdapter
|
|
87
|
-
def min_version
|
|
88
|
-
"8.0"
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def set_statement_timeout(timeout)
|
|
92
|
-
select_all("SET max_execution_time = #{timeout.to_i * 1000}")
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def check_lock_timeout
|
|
96
|
-
lock_timeout = connection.select_value("SELECT @@lock_wait_timeout")
|
|
97
|
-
# validation logic
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
## MariaDB Adapter (MySQL variant)
|
|
105
|
-
|
|
106
|
-
```ruby
|
|
107
|
-
# lib/strong_migrations/adapters/mariadb_adapter.rb
|
|
108
|
-
module StrongMigrations
|
|
109
|
-
module Adapters
|
|
110
|
-
class MariaDBAdapter < MySQLAdapter
|
|
111
|
-
def min_version
|
|
112
|
-
"10.5"
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
# Override MySQL-specific behavior
|
|
116
|
-
def set_statement_timeout(timeout)
|
|
117
|
-
select_all("SET max_statement_time = #{timeout.to_i}")
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
## Adapter Detection Pattern
|
|
125
|
-
|
|
126
|
-
Use regex matching on adapter name:
|
|
127
|
-
|
|
128
|
-
```ruby
|
|
129
|
-
def adapter
|
|
130
|
-
@adapter ||= case connection.adapter_name
|
|
131
|
-
when /postg/i
|
|
132
|
-
Adapters::PostgreSQLAdapter.new(self)
|
|
133
|
-
when /mysql|trilogy/i
|
|
134
|
-
if connection.try(:mariadb?)
|
|
135
|
-
Adapters::MariaDBAdapter.new(self)
|
|
136
|
-
else
|
|
137
|
-
Adapters::MySQLAdapter.new(self)
|
|
138
|
-
end
|
|
139
|
-
when /sqlite/i
|
|
140
|
-
Adapters::SQLiteAdapter.new(self)
|
|
141
|
-
else
|
|
142
|
-
Adapters::AbstractAdapter.new(self)
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
## Multi-Database Support (PgHero pattern)
|
|
148
|
-
|
|
149
|
-
```ruby
|
|
150
|
-
module PgHero
|
|
151
|
-
class << self
|
|
152
|
-
attr_accessor :databases
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
self.databases = {}
|
|
156
|
-
|
|
157
|
-
def self.primary_database
|
|
158
|
-
databases.values.first
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
def self.capture_query_stats(database: nil)
|
|
162
|
-
db = database ? databases[database] : primary_database
|
|
163
|
-
db.capture_query_stats
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
class Database
|
|
167
|
-
attr_reader :id, :config
|
|
168
|
-
|
|
169
|
-
def initialize(id, config)
|
|
170
|
-
@id = id
|
|
171
|
-
@config = config
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
def connection_model
|
|
175
|
-
@connection_model ||= begin
|
|
176
|
-
Class.new(ActiveRecord::Base) do
|
|
177
|
-
self.abstract_class = true
|
|
178
|
-
end.tap do |model|
|
|
179
|
-
model.establish_connection(config)
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
def connection
|
|
185
|
-
connection_model.connection
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
end
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
## Connection Switching
|
|
192
|
-
|
|
193
|
-
```ruby
|
|
194
|
-
def with_connection(database_name)
|
|
195
|
-
db = databases[database_name.to_s]
|
|
196
|
-
raise Error, "Unknown database: #{database_name}" unless db
|
|
197
|
-
|
|
198
|
-
yield db.connection
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
# Usage
|
|
202
|
-
PgHero.with_connection(:replica) do |conn|
|
|
203
|
-
conn.execute("SELECT * FROM users")
|
|
204
|
-
end
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
## SQL Dialect Handling
|
|
208
|
-
|
|
209
|
-
```ruby
|
|
210
|
-
def quote_column(column)
|
|
211
|
-
case adapter_name
|
|
212
|
-
when /postg/i
|
|
213
|
-
%("#{column}")
|
|
214
|
-
when /mysql/i
|
|
215
|
-
"`#{column}`"
|
|
216
|
-
else
|
|
217
|
-
column
|
|
218
|
-
end
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
def boolean_value(value)
|
|
222
|
-
case adapter_name
|
|
223
|
-
when /postg/i
|
|
224
|
-
value ? "true" : "false"
|
|
225
|
-
when /mysql/i
|
|
226
|
-
value ? "1" : "0"
|
|
227
|
-
else
|
|
228
|
-
value.to_s
|
|
229
|
-
end
|
|
230
|
-
end
|
|
231
|
-
```
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
# Module Organization Patterns
|
|
2
|
-
|
|
3
|
-
## Simple Gem Layout
|
|
4
|
-
|
|
5
|
-
```
|
|
6
|
-
lib/
|
|
7
|
-
├── gemname.rb # Entry point, config, errors
|
|
8
|
-
└── gemname/
|
|
9
|
-
├── helper.rb # Core functionality
|
|
10
|
-
├── engine.rb # Rails engine (if needed)
|
|
11
|
-
└── version.rb # VERSION constant only
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
## Complex Gem Layout (PgHero pattern)
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
lib/
|
|
18
|
-
├── pghero.rb
|
|
19
|
-
└── pghero/
|
|
20
|
-
├── database.rb # Main class
|
|
21
|
-
├── engine.rb # Rails engine
|
|
22
|
-
└── methods/ # Functional decomposition
|
|
23
|
-
├── basic.rb
|
|
24
|
-
├── connections.rb
|
|
25
|
-
├── indexes.rb
|
|
26
|
-
├── queries.rb
|
|
27
|
-
└── replication.rb
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## Method Decomposition Pattern
|
|
31
|
-
|
|
32
|
-
Break large classes into includable modules by feature:
|
|
33
|
-
|
|
34
|
-
```ruby
|
|
35
|
-
# lib/pghero/database.rb
|
|
36
|
-
module PgHero
|
|
37
|
-
class Database
|
|
38
|
-
include Methods::Basic
|
|
39
|
-
include Methods::Connections
|
|
40
|
-
include Methods::Indexes
|
|
41
|
-
include Methods::Queries
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# lib/pghero/methods/indexes.rb
|
|
46
|
-
module PgHero
|
|
47
|
-
module Methods
|
|
48
|
-
module Indexes
|
|
49
|
-
def index_hit_rate
|
|
50
|
-
# implementation
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def unused_indexes
|
|
54
|
-
# implementation
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## Version File Pattern
|
|
62
|
-
|
|
63
|
-
Keep version.rb minimal:
|
|
64
|
-
|
|
65
|
-
```ruby
|
|
66
|
-
# lib/gemname/version.rb
|
|
67
|
-
module GemName
|
|
68
|
-
VERSION = "2.0.0"
|
|
69
|
-
end
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## Require Order in Entry Point
|
|
73
|
-
|
|
74
|
-
```ruby
|
|
75
|
-
# lib/searchkick.rb
|
|
76
|
-
|
|
77
|
-
# 1. Standard library
|
|
78
|
-
require "forwardable"
|
|
79
|
-
require "json"
|
|
80
|
-
|
|
81
|
-
# 2. External dependencies (minimal)
|
|
82
|
-
require "active_support"
|
|
83
|
-
|
|
84
|
-
# 3. Internal files via require_relative
|
|
85
|
-
require_relative "searchkick/index"
|
|
86
|
-
require_relative "searchkick/model"
|
|
87
|
-
require_relative "searchkick/query"
|
|
88
|
-
require_relative "searchkick/version"
|
|
89
|
-
|
|
90
|
-
# 4. Conditional Rails loading (LAST)
|
|
91
|
-
require_relative "searchkick/railtie" if defined?(Rails)
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## Autoload vs Require
|
|
95
|
-
|
|
96
|
-
Kane uses explicit `require_relative`, not autoload:
|
|
97
|
-
|
|
98
|
-
```ruby
|
|
99
|
-
# CORRECT
|
|
100
|
-
require_relative "gemname/model"
|
|
101
|
-
require_relative "gemname/query"
|
|
102
|
-
|
|
103
|
-
# AVOID
|
|
104
|
-
autoload :Model, "gemname/model"
|
|
105
|
-
autoload :Query, "gemname/query"
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
## Comments Style
|
|
109
|
-
|
|
110
|
-
Minimal section headers only:
|
|
111
|
-
|
|
112
|
-
```ruby
|
|
113
|
-
# dependencies
|
|
114
|
-
require "active_support"
|
|
115
|
-
|
|
116
|
-
# adapters
|
|
117
|
-
require_relative "adapters/postgresql_adapter"
|
|
118
|
-
|
|
119
|
-
# modules
|
|
120
|
-
require_relative "migration"
|
|
121
|
-
```
|