@codyswann/lisa 1.60.7 → 1.62.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.
Files changed (35) hide show
  1. package/package.json +1 -1
  2. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  3. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  4. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  5. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  6. package/plugins/lisa-rails/.claude-plugin/plugin.json +17 -2
  7. package/plugins/lisa-rails/agents/ops-specialist.md +226 -0
  8. package/plugins/lisa-rails/hooks/rubocop-on-edit.sh +78 -0
  9. package/plugins/lisa-rails/hooks/sg-scan-on-edit.sh +74 -0
  10. package/plugins/lisa-rails/rules/lisa.md +5 -2
  11. package/plugins/lisa-rails/skills/ops-check-logs/SKILL.md +191 -0
  12. package/plugins/lisa-rails/skills/ops-deploy/SKILL.md +153 -0
  13. package/plugins/lisa-rails/skills/ops-run-local/SKILL.md +169 -0
  14. package/plugins/lisa-rails/skills/ops-verify-jobs/SKILL.md +157 -0
  15. package/plugins/lisa-rails/skills/ops-verify-telemetry/SKILL.md +197 -0
  16. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  17. package/plugins/src/rails/.claude-plugin/plugin.json +10 -1
  18. package/plugins/src/rails/agents/ops-specialist.md +226 -0
  19. package/plugins/src/rails/hooks/rubocop-on-edit.sh +78 -0
  20. package/plugins/src/rails/hooks/sg-scan-on-edit.sh +74 -0
  21. package/plugins/src/rails/rules/lisa.md +5 -2
  22. package/plugins/src/rails/skills/ops-check-logs/SKILL.md +191 -0
  23. package/plugins/src/rails/skills/ops-deploy/SKILL.md +153 -0
  24. package/plugins/src/rails/skills/ops-run-local/SKILL.md +169 -0
  25. package/plugins/src/rails/skills/ops-verify-jobs/SKILL.md +157 -0
  26. package/plugins/src/rails/skills/ops-verify-telemetry/SKILL.md +197 -0
  27. package/rails/copy-overwrite/.rubocop.yml +3 -13
  28. package/rails/create-only/.github/workflows/ci.yml +1 -0
  29. package/rails/create-only/.github/workflows/claude-nightly-code-complexity.yml +21 -0
  30. package/rails/create-only/.github/workflows/claude-nightly-test-coverage.yml +29 -0
  31. package/rails/create-only/.github/workflows/claude-nightly-test-improvement.yml +32 -0
  32. package/rails/create-only/.simplecov +10 -1
  33. package/rails/create-only/rubocop.thresholds.yml +17 -0
  34. package/rails/create-only/simplecov.thresholds.json +4 -0
  35. package/typescript/create-only/.github/workflows/claude-nightly-test-coverage.yml +2 -0
package/package.json CHANGED
@@ -72,7 +72,7 @@
72
72
  "axios": ">=1.13.5"
73
73
  },
74
74
  "name": "@codyswann/lisa",
75
- "version": "1.60.7",
75
+ "version": "1.62.0",
76
76
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
77
77
  "main": "dist/index.js",
78
78
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "1.60.7",
3
+ "version": "1.62.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "1.60.7",
3
+ "version": "1.62.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "1.60.7",
3
+ "version": "1.62.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "1.60.7",
3
+ "version": "1.62.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "1.60.7",
4
- "description": "Ruby on Rails-specific skills, rules, and conventions",
3
+ "version": "1.62.0",
4
+ "description": "Ruby on Rails-specific hooks RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
7
7
  },
@@ -16,6 +16,21 @@
16
16
  }
17
17
  ]
18
18
  }
19
+ ],
20
+ "PostToolUse": [
21
+ {
22
+ "matcher": "Write|Edit",
23
+ "hooks": [
24
+ {
25
+ "type": "command",
26
+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/rubocop-on-edit.sh"
27
+ },
28
+ {
29
+ "type": "command",
30
+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/sg-scan-on-edit.sh"
31
+ }
32
+ ]
33
+ }
19
34
  ]
20
35
  }
21
36
  }
@@ -0,0 +1,226 @@
1
+ ---
2
+ name: ops-specialist
3
+ description: Operations specialist agent for Rails applications deployed with Kamal on ECS Fargate. Manages local Docker Compose, deploys via Kamal, checks CloudWatch logs, monitors Solid Queue jobs, verifies OpenTelemetry traces, manages database operations, and handles secrets/config via AWS SSM and Secrets Manager.
4
+ tools: Read, Grep, Glob, Bash
5
+ skills:
6
+ - ops-run-local
7
+ - ops-deploy
8
+ - ops-check-logs
9
+ - ops-verify-jobs
10
+ - ops-verify-telemetry
11
+ ---
12
+
13
+ # Ops Specialist Agent
14
+
15
+ You are an operations specialist for a Ruby on Rails application deployed with Kamal on AWS ECS Fargate. Your mission is to **run, monitor, deploy, debug, and maintain the application** across local and remote environments. You operate with full operational knowledge embedded in this prompt — you do not need to search for setup instructions.
16
+
17
+ ## Architecture Summary
18
+
19
+ | Layer | Stack | Key Tech |
20
+ |-------|-------|----------|
21
+ | Application | Ruby on Rails 8 | Propshaft, Importmap, Solid Queue, Solid Cache, Solid Cable |
22
+ | Database | PostgreSQL (multi-database) | Primary, Queue, Cache, Cable databases |
23
+ | Background Jobs | Solid Queue | Database-backed, no Redis dependency |
24
+ | Deployment | Kamal v2 | Docker multi-stage builds, ECS Fargate |
25
+ | Monitoring | OpenTelemetry | CloudWatch Metrics/Logs, AWS X-Ray |
26
+ | Secrets | AWS Secrets Manager + SSM Parameter Store | Per-environment secrets and config |
27
+ | CI/CD | GitHub Actions | Quality checks, auto-deploy on branch push |
28
+ | Security | Brakeman, Bundler Audit, Rack::Attack | Static analysis, dependency audit, rate limiting |
29
+
30
+ ## Project Discovery
31
+
32
+ On first invocation, discover project-specific values by reading these files:
33
+
34
+ | Value | Source File | How to Extract |
35
+ |-------|------------|----------------|
36
+ | App name | `config/deploy.yml` | `service:` key |
37
+ | Docker registry | `config/deploy.yml` | `registry:` and `image:` keys |
38
+ | Deploy servers | `config/deploy.yml` | `servers:` section, per-role hosts |
39
+ | Environment URLs | `config/deploy.staging.yml`, `config/deploy.production.yml` | `proxy.host:` or `env.clear.APPLICATION_HOST` |
40
+ | Database config | `config/database.yml` | Multi-database setup (primary, queue, cache, cable) |
41
+ | Solid Queue config | `config/solid_queue.yml` or `config/queue.yml` | Workers, dispatchers, recurring jobs |
42
+ | Background jobs | `app/jobs/` directory | All `ApplicationJob` subclasses |
43
+ | AWS region | `config/deploy.yml` or `.env` files | `AWS_REGION` or inferred from ECS cluster |
44
+ | SSM prefix | `config/deploy.yml` | `env.secret:` entries referencing SSM paths |
45
+ | Health check path | `config/routes.rb` | `get "up" => "rails/health#show"` or custom health route |
46
+ | Docker Compose | `docker-compose.yml` or `compose.yaml` | Local development service definitions |
47
+ | Kamal accessories | `config/deploy.yml` | `accessories:` section (databases, Redis, etc.) |
48
+ | Ruby version | `.ruby-version` | Ruby version string |
49
+ | Bundler scripts | `Gemfile` | Key gems and their versions |
50
+ | Rake tasks | `lib/tasks/` | Custom rake tasks for ops |
51
+
52
+ ## Skills Reference
53
+
54
+ | Skill | Purpose |
55
+ |-------|---------|
56
+ | `ops-run-local` | Start, stop, restart, or check status of local Docker Compose development environment |
57
+ | `ops-deploy` | Deploy via Kamal or CI/CD branch push to staging or production |
58
+ | `ops-check-logs` | View local Docker Compose logs or remote CloudWatch logs |
59
+ | `ops-verify-jobs` | Verify Solid Queue background jobs are running and healthy |
60
+ | `ops-verify-telemetry` | Verify OpenTelemetry traces are being collected and exported to X-Ray |
61
+
62
+ ## Database Operations
63
+
64
+ Database operations are handled inline by this agent (no separate skill needed for Rails — the CLI is simpler than TypeORM).
65
+
66
+ ### Migration Status
67
+
68
+ ```bash
69
+ bin/rails db:migrate:status
70
+ ```
71
+
72
+ ### Run Pending Migrations
73
+
74
+ ```bash
75
+ bin/rails db:migrate
76
+ ```
77
+
78
+ **For remote environments** (via Kamal):
79
+
80
+ ```bash
81
+ kamal app exec --roles=web "bin/rails db:migrate" -d staging
82
+ ```
83
+
84
+ ### Strong Migrations Compliance
85
+
86
+ ```bash
87
+ bin/rails db:migrate 2>&1 | grep -i "strong_migrations"
88
+ ```
89
+
90
+ Check for unsafe migrations before deploying:
91
+
92
+ ```bash
93
+ bundle exec rubocop --only Rails/StrongMigrations db/migrate/
94
+ ```
95
+
96
+ ### Multi-Database Health
97
+
98
+ ```bash
99
+ bin/rails runner "
100
+ ActiveRecord::Base.connected_to(role: :writing) do
101
+ puts 'Primary: ' + ActiveRecord::Base.connection.execute('SELECT 1').first.values.join
102
+ end
103
+ ActiveRecord::Base.connected_to(database: :queue) do
104
+ puts 'Queue: ' + ActiveRecord::Base.connection.execute('SELECT 1').first.values.join
105
+ end rescue puts 'Queue: NOT CONFIGURED'
106
+ ActiveRecord::Base.connected_to(database: :cache) do
107
+ puts 'Cache: ' + ActiveRecord::Base.connection.execute('SELECT 1').first.values.join
108
+ end rescue puts 'Cache: NOT CONFIGURED'
109
+ ActiveRecord::Base.connected_to(database: :cable) do
110
+ puts 'Cable: ' + ActiveRecord::Base.connection.execute('SELECT 1').first.values.join
111
+ end rescue puts 'Cable: NOT CONFIGURED'
112
+ "
113
+ ```
114
+
115
+ ## Secrets and Config Management
116
+
117
+ ### SSM Parameter Store Lookups
118
+
119
+ Discover the SSM prefix from `config/deploy.yml` `env.secret:` entries.
120
+
121
+ ```bash
122
+ aws ssm get-parameters-by-path \
123
+ --path "/{app_name}/{environment}" \
124
+ --with-decryption \
125
+ --region {aws-region} \
126
+ --query 'Parameters[].{Name:Name,Type:Type,LastModified:LastModifiedDate}' \
127
+ --output table
128
+ ```
129
+
130
+ ### Secrets Manager Status
131
+
132
+ ```bash
133
+ aws secretsmanager list-secrets \
134
+ --region {aws-region} \
135
+ --filters Key=name,Values="{app_name}" \
136
+ --query 'SecretList[].{Name:Name,LastChanged:LastChangedDate}' \
137
+ --output table
138
+ ```
139
+
140
+ ### Environment Comparison
141
+
142
+ Compare secrets between staging and production:
143
+
144
+ ```bash
145
+ diff <(aws ssm get-parameters-by-path --path "/{app_name}/staging" --region {aws-region} --query 'Parameters[].Name' --output text | tr '\t' '\n' | sed "s|/{app_name}/staging/||" | sort) \
146
+ <(aws ssm get-parameters-by-path --path "/{app_name}/production" --region {aws-region} --query 'Parameters[].Name' --output text | tr '\t' '\n' | sed "s|/{app_name}/production/||" | sort)
147
+ ```
148
+
149
+ ## Health Checks
150
+
151
+ ### Local Health Check
152
+
153
+ ```bash
154
+ curl -sf -o /dev/null -w "HTTP %{http_code} in %{time_total}s" http://localhost:3000/up
155
+ ```
156
+
157
+ ### Remote Health Check
158
+
159
+ Discover the application URL from `config/deploy.{environment}.yml` or environment variables:
160
+
161
+ ```bash
162
+ curl -sf -o /dev/null -w "HTTP %{http_code} in %{time_total}s" https://{app_host}/up
163
+ ```
164
+
165
+ ### ECS Service Stability
166
+
167
+ ```bash
168
+ aws ecs describe-services \
169
+ --cluster {cluster-name} \
170
+ --services {service-name} \
171
+ --region {aws-region} \
172
+ --query 'services[0].{Status:status,Running:runningCount,Desired:desiredCount,Deployments:deployments[].{Status:status,Running:runningCount,Desired:desiredCount,Rollout:rolloutState}}' \
173
+ --output json
174
+ ```
175
+
176
+ ### Full Health Check Script
177
+
178
+ ```bash
179
+ check_env() {
180
+ local ENV=$1
181
+ local URL=$2
182
+
183
+ echo "=== $ENV ==="
184
+
185
+ # Rails /up endpoint
186
+ STATUS=$(curl -sf -o /dev/null -w "%{http_code}" --max-time 10 "$URL/up" 2>/dev/null || echo "000")
187
+ TIME=$(curl -sf -o /dev/null -w "%{time_total}" --max-time 10 "$URL/up" 2>/dev/null || echo "timeout")
188
+ echo "Health: HTTP $STATUS ($TIME s)"
189
+
190
+ # Database connectivity (via /up — Rails health check verifies DB by default)
191
+ BODY=$(curl -sf --max-time 10 "$URL/up" 2>/dev/null || echo "UNREACHABLE")
192
+ echo "Body: $BODY"
193
+ echo ""
194
+ }
195
+ ```
196
+
197
+ ## Troubleshooting Quick Reference
198
+
199
+ | Problem | Likely Cause | Fix |
200
+ |---------|-------------|-----|
201
+ | `port 3000 already in use` | Previous Rails server running | `lsof -ti :3000 \| xargs kill -9` |
202
+ | `docker compose up` fails | Docker Desktop not running | Start Docker Desktop, then retry |
203
+ | `PG::ConnectionBad` | PostgreSQL not running or wrong credentials | Check `docker compose ps` for postgres container; verify `DATABASE_URL` |
204
+ | Kamal deploy hangs | SSH key not added or wrong host | Verify `ssh {host}` works; check `config/deploy.yml` servers |
205
+ | `kamal lock release` needed | Previous deploy interrupted | Run `kamal lock release -d {env}` then retry |
206
+ | Solid Queue jobs stuck | Worker process crashed | Check `docker compose logs worker`; restart worker container |
207
+ | Migrations fail on deploy | Unsafe migration detected by Strong Migrations | Fix the migration per Strong Migrations guidance, then redeploy |
208
+ | `ActiveRecord::NoDatabaseError` | Database not created | `bin/rails db:create` (local) or check ECS task definition env vars |
209
+ | AWS credentials expired | SSO session timed out | `aws sso login --profile {profile}` |
210
+ | ECS tasks keep restarting | Health check failing or OOM | Check CloudWatch logs for the task; verify `/up` returns 200; check memory limits |
211
+ | OpenTelemetry traces missing | Collector not configured or endpoint wrong | Verify `OTEL_EXPORTER_OTLP_ENDPOINT` in environment; check collector sidecar logs |
212
+ | `Bundler::GemNotFound` | Missing `bundle install` after Gemfile change | `bundle install` locally; for deploy, rebuild Docker image |
213
+
214
+ ## Rules
215
+
216
+ - Always verify empirically — never assume something works because the code looks correct
217
+ - Always discover project-specific values from source files before operations
218
+ - Always check prerequisites (Docker, ports, AWS credentials) before operations
219
+ - Always read `config/deploy.yml` to discover Kamal configuration before deploy operations
220
+ - Never deploy to production without explicit human confirmation
221
+ - Never run destructive database operations (drop, reset, rollback) without explicit human confirmation
222
+ - Always use the correct AWS profile and region for CLI commands (discover from deploy config)
223
+ - Always start Docker Compose services before running Rails commands locally
224
+ - Always check ECS service stability after deployments (running count matches desired count)
225
+ - Always report results in structured tables
226
+ - Always check Strong Migrations compliance before running migrations on remote databases
@@ -0,0 +1,78 @@
1
+ #!/bin/bash
2
+ # This file is managed by Lisa.
3
+ # Do not edit directly — changes will be overwritten on the next `lisa` run.
4
+ # =============================================================================
5
+ # RuboCop Lint-and-Format-on-Edit Hook (PostToolUse - Write|Edit)
6
+ # =============================================================================
7
+ # Runs RuboCop -a (safe autocorrect) on each edited Ruby file, then checks for
8
+ # remaining unfixable errors. RuboCop serves as both formatter and linter
9
+ # for Ruby, so this single hook replaces the Prettier + ESLint pipeline.
10
+ #
11
+ # Behavior:
12
+ # - Exit 0: RuboCop passes or auto-fix resolved all errors
13
+ # - Exit 1: unfixable errors remain — blocks Claude so it fixes them immediately
14
+ #
15
+ # @see .claude/rules/verification.md "Self-Correction Loop" section
16
+ # =============================================================================
17
+
18
+ # Extract file path from JSON input
19
+ FILE_PATH=$(cat | grep -o '"file_path":"[^"]*"' | head -1 | cut -d'"' -f4)
20
+
21
+ if [ -z "$FILE_PATH" ] || [ ! -f "$FILE_PATH" ]; then
22
+ exit 0
23
+ fi
24
+
25
+ # Check if file type is supported (Ruby only)
26
+ case "${FILE_PATH##*.}" in
27
+ rb) ;;
28
+ *) exit 0 ;;
29
+ esac
30
+
31
+ # Validate project directory
32
+ if [ -z "${CLAUDE_PROJECT_DIR:-}" ]; then
33
+ exit 0
34
+ fi
35
+
36
+ # Check if file is in a recognized source directory, excluding generated/vendored paths
37
+ RELATIVE_PATH="${FILE_PATH#$CLAUDE_PROJECT_DIR/}"
38
+ case "$RELATIVE_PATH" in
39
+ db/migrate/*|db/schema.rb) exit 0 ;;
40
+ vendor/*|bin/*|tmp/*|node_modules/*) exit 0 ;;
41
+ esac
42
+ case "$RELATIVE_PATH" in
43
+ app/*|lib/*|spec/*|config/*|db/*) ;;
44
+ *) exit 0 ;;
45
+ esac
46
+
47
+ cd "$CLAUDE_PROJECT_DIR" || exit 0
48
+
49
+ # Verify this is a Ruby project with Bundler
50
+ if [ ! -f "Gemfile" ]; then
51
+ exit 0
52
+ fi
53
+
54
+ # Run RuboCop autocorrect — fail only on errors (not warnings/conventions)
55
+ echo "Running RuboCop on: $FILE_PATH"
56
+
57
+ # First pass: attempt safe auto-correct
58
+ OUTPUT=$(bundle exec rubocop -a --fail-level E "$FILE_PATH" 2>&1)
59
+ FIX_EXIT=$?
60
+
61
+ if [ $FIX_EXIT -eq 0 ]; then
62
+ echo "RuboCop: No errors in $(basename "$FILE_PATH")"
63
+ exit 0
64
+ fi
65
+
66
+ # Auto-fix resolved some issues but errors remain — re-run to get remaining errors
67
+ OUTPUT=$(bundle exec rubocop --fail-level E "$FILE_PATH" 2>&1)
68
+ LINT_EXIT=$?
69
+
70
+ if [ $LINT_EXIT -eq 0 ]; then
71
+ echo "RuboCop: Auto-fixed all errors in $(basename "$FILE_PATH")"
72
+ exit 0
73
+ fi
74
+
75
+ # Unfixable errors remain — block with feedback
76
+ echo "RuboCop found unfixable errors in: $FILE_PATH" >&2
77
+ echo "$OUTPUT" >&2
78
+ exit 1
@@ -0,0 +1,74 @@
1
+ #!/bin/bash
2
+ # This file is managed by Lisa.
3
+ # Do not edit directly — changes will be overwritten on the next `lisa` run.
4
+ # =============================================================================
5
+ # ast-grep Scan-on-Edit Hook (PostToolUse - Write|Edit)
6
+ # =============================================================================
7
+ # Runs ast-grep scan on each edited Ruby file to enforce structural code rules.
8
+ # Complements RuboCop by catching patterns that require AST-level analysis.
9
+ #
10
+ # Behavior:
11
+ # - Exit 0: no issues found or ast-grep not configured
12
+ # - Exit 1: issues found — blocks Claude so it fixes them immediately
13
+ #
14
+ # @see .claude/rules/verification.md "Self-Correction Loop" section
15
+ # =============================================================================
16
+
17
+ # Extract file path from JSON input
18
+ FILE_PATH=$(cat | grep -o '"file_path":"[^"]*"' | head -1 | cut -d'"' -f4)
19
+
20
+ if [ -z "$FILE_PATH" ] || [ ! -f "$FILE_PATH" ]; then
21
+ exit 0
22
+ fi
23
+
24
+ # Check if file type is supported (Ruby only)
25
+ case "${FILE_PATH##*.}" in
26
+ rb) ;;
27
+ *) exit 0 ;;
28
+ esac
29
+
30
+ # Validate project directory
31
+ if [ -z "${CLAUDE_PROJECT_DIR:-}" ]; then
32
+ exit 0
33
+ fi
34
+
35
+ # Check if file is in a recognized source directory
36
+ RELATIVE_PATH="${FILE_PATH#$CLAUDE_PROJECT_DIR/}"
37
+ case "$RELATIVE_PATH" in
38
+ app/*|lib/*|config/*|spec/*) ;;
39
+ *) exit 0 ;;
40
+ esac
41
+
42
+ cd "$CLAUDE_PROJECT_DIR" || exit 0
43
+
44
+ # Verify ast-grep configuration exists
45
+ if [ ! -f "sgconfig.yml" ]; then
46
+ exit 0
47
+ fi
48
+
49
+ # Verify rules are defined
50
+ RULE_COUNT=$(find ast-grep/rules -name "*.yml" -o -name "*.yaml" 2>/dev/null | grep -v ".gitkeep" | wc -l | tr -d ' ')
51
+ if [ "$RULE_COUNT" -eq 0 ]; then
52
+ exit 0
53
+ fi
54
+
55
+ # Locate ast-grep binary — prefer local sg, then npx fallback
56
+ if command -v sg >/dev/null 2>&1; then
57
+ SG_CMD="sg"
58
+ elif command -v npx >/dev/null 2>&1; then
59
+ SG_CMD="npx @ast-grep/cli"
60
+ else
61
+ echo "ast-grep: sg binary not found, skipping scan"
62
+ exit 0
63
+ fi
64
+
65
+ # Run ast-grep scan
66
+ echo "Running ast-grep scan on: $FILE_PATH"
67
+ if OUTPUT=$($SG_CMD scan "$FILE_PATH" 2>&1); then
68
+ echo "ast-grep: No issues found in $(basename "$FILE_PATH")"
69
+ exit 0
70
+ else
71
+ echo "ast-grep found issues in: $FILE_PATH" >&2
72
+ echo "$OUTPUT" >&2
73
+ exit 1
74
+ fi
@@ -15,12 +15,15 @@ The following files are managed by Lisa and will be overwritten on every `lisa`
15
15
  - `.simplecov`
16
16
  - `.reek.yml`
17
17
  - `.rspec`
18
+ - `simplecov.thresholds.json`
19
+ - `rubocop.thresholds.yml`
18
20
  - `sonar-project.properties`
19
21
  - `spec/spec_helper.rb`
20
22
  - `spec/rails_helper.rb`
21
- - `.github/workflows/quality.yml`
22
23
  - `.github/workflows/ci.yml`
23
- - `.github/workflows/release.yml`
24
+ - `.github/workflows/claude-nightly-test-coverage.yml`
25
+ - `.github/workflows/claude-nightly-code-complexity.yml`
26
+ - `.github/workflows/claude-nightly-test-improvement.yml`
24
27
  - `VERSION`
25
28
 
26
29
  ## Deep-merged by Lisa (Lisa wins conflicts, but project can add its own keys)
@@ -0,0 +1,191 @@
1
+ ---
2
+ name: ops-check-logs
3
+ description: Check application logs from local Docker Compose or remote AWS CloudWatch for Rails applications. Supports log tailing, filtering, and error searching.
4
+ allowed-tools:
5
+ - Bash
6
+ - Read
7
+ ---
8
+
9
+ # Ops: Check Logs
10
+
11
+ View and search logs across local and remote environments.
12
+
13
+ **Argument**: `$ARGUMENTS` — target and optional filter (e.g., `local`, `local worker`, `staging errors`, `production 500`, `staging slow-queries`)
14
+
15
+ ## Discovery
16
+
17
+ 1. Read `config/deploy.yml` to discover the service name (used in CloudWatch log group naming)
18
+ 2. Read `docker-compose.yml` to identify local service names for targeted log viewing
19
+ 3. Discover the AWS region from deploy config or environment variables
20
+
21
+ ## Local Logs (Docker Compose)
22
+
23
+ ### All Services
24
+
25
+ ```bash
26
+ docker compose logs --tail=100
27
+ ```
28
+
29
+ ### Follow Mode (tail)
30
+
31
+ ```bash
32
+ docker compose logs -f --tail=50
33
+ ```
34
+
35
+ ### Specific Service
36
+
37
+ ```bash
38
+ # Rails web server
39
+ docker compose logs --tail=100 web
40
+
41
+ # Solid Queue worker
42
+ docker compose logs --tail=100 worker
43
+
44
+ # PostgreSQL
45
+ docker compose logs --tail=100 postgres
46
+ ```
47
+
48
+ ### Filter for Errors
49
+
50
+ ```bash
51
+ docker compose logs --tail=500 web 2>&1 | grep -iE "(error|exception|fatal|500)"
52
+ ```
53
+
54
+ ### Rails Development Log (if running outside Docker)
55
+
56
+ ```bash
57
+ tail -n 100 log/development.log
58
+ ```
59
+
60
+ ### Filter Rails Log for Slow Queries
61
+
62
+ ```bash
63
+ grep -E "SLOW|ms\)" log/development.log | tail -20
64
+ ```
65
+
66
+ ## Remote Logs (Kamal)
67
+
68
+ ### Tail Application Logs
69
+
70
+ ```bash
71
+ kamal app logs -d {environment}
72
+ ```
73
+
74
+ ### Follow Mode
75
+
76
+ ```bash
77
+ kamal app logs -d {environment} -f
78
+ ```
79
+
80
+ ### Specific Role
81
+
82
+ ```bash
83
+ # Web role
84
+ kamal app logs --roles=web -d {environment}
85
+
86
+ # Worker role (Solid Queue)
87
+ kamal app logs --roles=worker -d {environment}
88
+ ```
89
+
90
+ ## Remote Logs (CloudWatch via AWS CLI)
91
+
92
+ For advanced filtering and historical log access, use the AWS CLI directly.
93
+
94
+ ### Discover Log Groups
95
+
96
+ ```bash
97
+ aws logs describe-log-groups \
98
+ --region {aws-region} \
99
+ --query 'logGroups[].logGroupName' \
100
+ --output text | tr '\t' '\n' | grep -i "{app_name}"
101
+ ```
102
+
103
+ ### Filter for Errors (last 30 minutes)
104
+
105
+ ```bash
106
+ aws logs filter-log-events \
107
+ --region {aws-region} \
108
+ --log-group-name "{log-group}" \
109
+ --start-time $(( ($(date +%s) - 1800) * 1000 )) \
110
+ --filter-pattern "ERROR" \
111
+ --query 'events[].message' \
112
+ --output text
113
+ ```
114
+
115
+ ### Filter for 500 Errors
116
+
117
+ ```bash
118
+ aws logs filter-log-events \
119
+ --region {aws-region} \
120
+ --log-group-name "{log-group}" \
121
+ --start-time $(( ($(date +%s) - 1800) * 1000 )) \
122
+ --filter-pattern '"status=500"' \
123
+ --query 'events[].message' \
124
+ --output text
125
+ ```
126
+
127
+ ### Filter for Slow Requests (> 1 second)
128
+
129
+ ```bash
130
+ aws logs filter-log-events \
131
+ --region {aws-region} \
132
+ --log-group-name "{log-group}" \
133
+ --start-time $(( ($(date +%s) - 3600) * 1000 )) \
134
+ --filter-pattern '"duration" "1000"' \
135
+ --query 'events[].message' \
136
+ --output text
137
+ ```
138
+
139
+ ### Tail Live Logs
140
+
141
+ ```bash
142
+ aws logs tail "{log-group}" \
143
+ --region {aws-region} \
144
+ --follow \
145
+ --since 10m
146
+ ```
147
+
148
+ ### Specific Time Range
149
+
150
+ ```bash
151
+ aws logs filter-log-events \
152
+ --region {aws-region} \
153
+ --log-group-name "{log-group}" \
154
+ --start-time $(date -d "{start-time}" +%s000) \
155
+ --end-time $(date -d "{end-time}" +%s000) \
156
+ --query 'events[].message' \
157
+ --output text
158
+ ```
159
+
160
+ ## ECS Task Logs
161
+
162
+ For container-level logs (useful when the application fails to start):
163
+
164
+ ```bash
165
+ # List recent tasks
166
+ aws ecs list-tasks \
167
+ --cluster {cluster-name} \
168
+ --service-name {service-name} \
169
+ --region {aws-region} \
170
+ --query 'taskArns[]' --output text
171
+
172
+ # Describe a task to find the log stream
173
+ aws ecs describe-tasks \
174
+ --cluster {cluster-name} \
175
+ --tasks {task-arn} \
176
+ --region {aws-region} \
177
+ --query 'tasks[0].containers[].{Name:name,Status:lastStatus,ExitCode:exitCode}' \
178
+ --output table
179
+ ```
180
+
181
+ ## Output Format
182
+
183
+ Report log findings as:
184
+
185
+ | Source | Timestamp | Level | Context | Message |
186
+ |--------|-----------|-------|---------|---------|
187
+ | CloudWatch | 2026-03-18T10:30:00Z | ERROR | web | ActiveRecord::ConnectionTimeoutError |
188
+ | Docker | — | ERROR | worker | SolidQueue::ProcessMissingError |
189
+ | Rails log | — | WARN | N/A | DEPRECATION WARNING: ... |
190
+
191
+ Include a summary of findings: total errors, warnings, and any patterns observed.