rails-ai-context 1.3.0 → 1.3.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aeeb02e9069ff67b12236ae2f99f169df5b5dd48d42af344ad0734ff1a499307
4
- data.tar.gz: 0d5f18c57c512747bc06fc063c9e58c95073f288df15f3d74bd0d951815fabe8
3
+ metadata.gz: d83d1237d476138591f50c4723cb10a4864aed5ed2e84b7059e53bff287af1db
4
+ data.tar.gz: 3791bba4e68364ea507050f2605096ce8dff2cacf943ddd111753b768c8152cf
5
5
  SHA512:
6
- metadata.gz: dc0c90e9d22ff8348ce6eefc770ca36eac77bda624795be2813972de0f56b565180bfc974042cc7fa949718a8362c760d3db9123dc8aab294403ca9498efd8f3
7
- data.tar.gz: f33d929cf59fdd217d4905a49b5043b689cb7828588ff738d9973d2e97c42f78228327d3574d276180e04663cac3f3470c7b84bc118022d9dc8890a47ff117ed
6
+ metadata.gz: 4e3ceb93281e5d3674aab290728357ef75d9d0c24a7d3cee05c9380333ba4d5209b13fdad85a7f015185697d09b9c9093fafc10e628d4dbc1bb897280eb5c388
7
+ data.tar.gz: 4a0240af3fc7a4ecc303c72107b62f5f5df88fafc189be1f3b19096895dccdd7242ce6e640f7d0f6f148aaed45af7e74f4bf717f773aee3b8cd77107f393c6b0
data/CHANGELOG.md CHANGED
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.3.1] - 2026-03-23
9
+
10
+ ### Fixed
11
+
12
+ - **Documentation audit** — updated tool count from 14 to 15 across README, GUIDE, CONTRIBUTING, server.json. Added `rails_get_design_system` documentation section to GUIDE.md. Updated SECURITY.md supported versions. Fixed spec count in CLAUDE.md. Added `rails_get_design_system` to README tool table. Updated `rails_analyze_feature` description to reflect full-stack discovery (services, jobs, views, Stimulus, tests, related models, env deps).
13
+ - **analyze_feature crash on complex models** — added type guards (`is_a?(Hash)`, `is_a?(Array)`) to all data access points preventing `no implicit conversion of Symbol into Integer` errors on models with many associations or complex data.
14
+
8
15
  ## [1.3.0] - 2026-03-23
9
16
 
10
17
  ### Added
data/CLAUDE.md CHANGED
@@ -45,7 +45,7 @@ structure to AI assistants via the Model Context Protocol (MCP).
45
45
  ## Testing
46
46
 
47
47
  ```bash
48
- bundle exec rspec # Run specs (520 examples)
48
+ bundle exec rspec # Run specs (522 examples)
49
49
  bundle exec rubocop # Lint
50
50
  ```
51
51
 
data/CONTRIBUTING.md CHANGED
@@ -19,7 +19,7 @@ The test suite uses [Combustion](https://github.com/pat/combustion) to boot a mi
19
19
  ```
20
20
  lib/rails_ai_context/
21
21
  ├── introspectors/ # 29 introspectors (schema, models, routes, etc.)
22
- ├── tools/ # 14 MCP tools with detail levels and pagination
22
+ ├── tools/ # 15 MCP tools with detail levels and pagination
23
23
  ├── serializers/ # Per-assistant formatters (claude, opencode, cursor, windsurf, copilot, JSON)
24
24
  ├── server.rb # MCP server setup (stdio + HTTP)
25
25
  ├── live_reload.rb # MCP live reload (file watcher + cache invalidation)
data/README.md CHANGED
@@ -62,7 +62,7 @@ Agent: rails_validate(files:["app/models/cook.rb"], level:"rails") → catches c
62
62
  |-------|-----------------|---------------|------------|
63
63
  | **Static files** (CLAUDE.md, .cursorrules, etc.) | App overview: stack, models, gems, architecture, UI patterns, MCP tool reference | Automatically at session start | ~150 lines, zero tool calls |
64
64
  | **Split rules** (.claude/rules/, .cursor/rules/) | Deep reference: full schema with column types, all model associations/scopes, controller listings | Conditionally — only when editing relevant files | Zero when not needed |
65
- | **Live MCP tools** (14 tools) | Real-time queries: drill into any table, model, controller action, or view on demand. Semantic validation. | On-demand via agent tool calls | ~25-100 lines per call |
65
+ | **Live MCP tools** (15 tools) | Real-time queries: drill into any table, model, controller action, or view on demand. Semantic validation. Design system. | On-demand via agent tool calls | ~25-100 lines per call |
66
66
 
67
67
  **Progressive disclosure:** the agent gets the map for free, reference guides when relevant, and live GPS when building.
68
68
 
@@ -72,7 +72,7 @@ Agent: rails_validate(files:["app/models/cook.rb"], level:"rails") → catches c
72
72
 
73
73
  | Setup | Tokens | What it knows |
74
74
  |-------|--------|---------------|
75
- | **rails-ai-context (full)** | **28,834** | 14 MCP tools + generated docs + split rules |
75
+ | **rails-ai-context (full)** | **28,834** | 15 MCP tools + generated docs + split rules |
76
76
  | rails-ai-context CLAUDE.md only | 33,106 | Generated docs + rules, no MCP tools |
77
77
  | Normal Claude `/init` | 40,700 | Generic CLAUDE.md only |
78
78
  | No rails-ai-context | 45,477 | Nothing — discovers everything from scratch |
@@ -97,9 +97,9 @@ But token savings is the side effect. The real value:
97
97
 
98
98
  ---
99
99
 
100
- ## 14 Live MCP Tools
100
+ ## 15 Live MCP Tools
101
101
 
102
- The gem exposes **14 read-only tools** via MCP that AI clients call on-demand:
102
+ The gem exposes **15 read-only tools** via MCP that AI clients call on-demand:
103
103
 
104
104
  | Tool | What it returns |
105
105
  |------|----------------|
@@ -116,7 +116,8 @@ The gem exposes **14 read-only tools** via MCP that AI clients call on-demand:
116
116
  | `rails_get_stimulus` | Stimulus controllers — targets, values, actions, outlets |
117
117
  | `rails_get_edit_context` | Surgical edit helper — returns code around a match with line numbers |
118
118
  | `rails_validate` | Batch syntax validation for Ruby, ERB, and JavaScript files. `level:"rails"` adds semantic checks (partials, route helpers, columns, strong params, callbacks, FK indexes, Stimulus) |
119
- | `rails_analyze_feature` | End-to-end feature analysis — finds matching models, controllers, routes, and views in one call |
119
+ | `rails_analyze_feature` | Full-stack feature analysis — models, controllers, routes, services, jobs, views, Stimulus, tests, related models, env deps |
120
+ | `rails_get_design_system` | App design system — color palette, component patterns with real HTML examples, typography, layout, responsive breakpoints |
120
121
 
121
122
  ### Smart Detail Levels
122
123
 
data/SECURITY.md CHANGED
@@ -4,10 +4,9 @@
4
4
 
5
5
  | Version | Supported |
6
6
  |---------|--------------------|
7
+ | 1.3.x | :white_check_mark: |
7
8
  | 1.2.x | :white_check_mark: |
8
- | 1.1.x | :white_check_mark: |
9
- | 1.0.x | :white_check_mark: |
10
- | < 1.0 | :x: |
9
+ | < 1.2 | :x: |
11
10
 
12
11
  ## Reporting a Vulnerability
13
12
 
data/docs/GUIDE.md CHANGED
@@ -252,7 +252,7 @@ rails ai:context:claude # Use this instead (no quoting needed)
252
252
 
253
253
  ## MCP Tools — Full Reference
254
254
 
255
- All 14 tools are **read-only** and **idempotent** — they never modify your application or database.
255
+ All 15 tools are **read-only** and **idempotent** — they never modify your application or database.
256
256
 
257
257
  ### rails_get_schema
258
258
 
@@ -590,7 +590,7 @@ rails_search_code(pattern: "validates", context_lines: 2)
590
590
 
591
591
  ### rails_analyze_feature
592
592
 
593
- Analyzes a feature end-to-end: finds matching models, controllers, routes, and views in one call.
593
+ Full-stack feature analysis: models, controllers, routes, services, jobs, views, Stimulus controllers, tests, related models, concerns, callbacks, channels, mailers, and environment dependencies in one call.
594
594
 
595
595
  **Parameters:**
596
596
 
@@ -616,7 +616,34 @@ rails_analyze_feature(feature: "orders")
616
616
  → Everything related to orders across all layers
617
617
  ```
618
618
 
619
- **Returns:** Markdown with sections for Models (with table, columns, indexes, FKs, associations, validations, scopes), Controllers (with actions and filters), and Routes (with verbs, paths, and route names). Each section shows match counts.
619
+ **Returns:** Markdown with sections for Models (with columns, associations, validations, scopes, enums), Controllers (with actions and filters), Routes, Services (with methods), Jobs (with queue/retry), Views (with partials and Stimulus refs), Stimulus controllers (with targets/values/actions), Tests (with counts), Related models, Concerns, Callbacks, Channels, Mailers, and Environment dependencies. Each section shows match counts.
620
+
621
+ ### rails_get_design_system
622
+
623
+ Returns the app's design system: color palette with semantic roles, component patterns with real HTML examples from actual views, typography scale, layout conventions, responsive breakpoints, and interactive state patterns.
624
+
625
+ **Parameters:**
626
+
627
+ | Param | Type | Description |
628
+ |-------|------|-------------|
629
+ | `detail` | string | `summary` (palette + components), `standard` (+ canonical page examples + design rules, default), `full` (+ typography, responsive, dark mode, animations, design tokens) |
630
+
631
+ **Examples:**
632
+
633
+ ```
634
+ rails_get_design_system()
635
+ → Color palette (primary, danger, success), component patterns (buttons, cards, inputs),
636
+ canonical page examples (form page, list page), design rules
637
+
638
+ rails_get_design_system(detail: "summary")
639
+ → Compact: color roles + component class strings only
640
+
641
+ rails_get_design_system(detail: "full")
642
+ → Everything: + typography scale, responsive breakpoints, interactive states,
643
+ dark mode patterns, animations, icon system, design tokens, shared partials
644
+ ```
645
+
646
+ **Returns:** Structured design system reference. Includes real HTML/ERB snippets from the app's actual views as canonical examples, semantic color roles (primary for CTAs, danger for destructive), component variants, typography hierarchy, spacing scale, and explicit design rules for AI to follow.
620
647
 
621
648
  ### Detail Level Summary
622
649
 
@@ -746,7 +773,7 @@ RailsAiContext.configure do |config|
746
773
  end
747
774
  ```
748
775
 
749
- Both transports are **read-only** — they expose the same 14 tools and never modify your app.
776
+ Both transports are **read-only** — they expose the same 15 tools and never modify your app.
750
777
 
751
778
  ---
752
779
 
@@ -74,10 +74,16 @@ module RailsAiContext
74
74
  end
75
75
  end
76
76
 
77
- lines << "**Associations:** #{data[:associations].map { |a| "#{a[:type]} :#{a[:name]}" }.join(', ')}" if data[:associations]&.any?
78
- lines << "**Validations:** #{data[:validations].map { |v| "#{v[:kind]} on #{v[:attributes].join(', ')}" }.uniq.join('; ')}" if data[:validations]&.any?
79
- lines << "**Scopes:** #{data[:scopes].join(', ')}" if data[:scopes]&.any?
80
- lines << "**Enums:** #{data[:enums].map { |k, v| "#{k}: #{v.join(', ')}" }.join('; ')}" if data[:enums]&.any?
77
+ if data[:associations].is_a?(Array) && data[:associations].any?
78
+ lines << "**Associations:** #{data[:associations].select { |a| a.is_a?(Hash) }.map { |a| "#{a[:type]} :#{a[:name]}" }.join(', ')}"
79
+ end
80
+ if data[:validations].is_a?(Array) && data[:validations].any?
81
+ lines << "**Validations:** #{data[:validations].select { |v| v.is_a?(Hash) }.map { |v| "#{v[:kind]} on #{Array(v[:attributes]).join(', ')}" }.uniq.join('; ')}"
82
+ end
83
+ lines << "**Scopes:** #{data[:scopes].join(', ')}" if data[:scopes].is_a?(Array) && data[:scopes].any?
84
+ if data[:enums].is_a?(Hash) && data[:enums].any?
85
+ lines << "**Enums:** #{data[:enums].map { |k, v| "#{k}: #{Array(v).join(', ')}" }.join('; ')}"
86
+ end
81
87
  end
82
88
  else
83
89
  lines << "## Models" << "_No models matching '#{pattern}'._"
@@ -90,7 +96,7 @@ module RailsAiContext
90
96
  # --- AF: Controllers ---
91
97
  def discover_controllers(ctx, pattern, lines)
92
98
  controllers = ctx.dig(:controllers, :controllers) || {}
93
- matched = controllers.select { |name, data| !data[:error] && name.downcase.include?(pattern) }
99
+ matched = controllers.select { |name, data| data.is_a?(Hash) && !data[:error] && name.downcase.include?(pattern) }
94
100
 
95
101
  if matched.any?
96
102
  lines << "## Controllers (#{matched.size})"
@@ -98,10 +104,10 @@ module RailsAiContext
98
104
  actions = info[:actions]&.join(", ") || "none"
99
105
  lines << "" << "### #{name}"
100
106
  lines << "- **Actions:** #{actions}"
101
- filters = (info[:filters] || []).map do |f|
107
+ filters = (info[:filters] || []).select { |f| f.is_a?(Hash) }.map do |f|
102
108
  label = "#{f[:kind]} #{f[:name]}"
103
- label += " only: #{f[:only].join(', ')}" if f[:only]&.any?
104
- label += " except: #{f[:except].join(', ')}" if f[:except]&.any?
109
+ label += " only: #{Array(f[:only]).join(', ')}" if f[:only]&.any?
110
+ label += " except: #{Array(f[:except]).join(', ')}" if f[:except]&.any?
105
111
  label += " unless: #{f[:unless]}" if f[:unless]
106
112
  label
107
113
  end
@@ -224,9 +230,18 @@ module RailsAiContext
224
230
  matched.each do |c|
225
231
  name = c[:name] || c[:file]&.gsub("_controller.js", "")
226
232
  lines << "" << "### #{name}"
227
- lines << "- **Targets:** #{c[:targets].join(', ')}" if c[:targets]&.any?
228
- lines << "- **Values:** #{c[:values].map { |v| "#{v[:name]}:#{v[:type]}" }.join(', ')}" if c[:values]&.any?
229
- lines << "- **Actions:** #{c[:actions].join(', ')}" if c[:actions]&.any?
233
+ lines << "- **Targets:** #{Array(c[:targets]).join(', ')}" if c[:targets]&.any?
234
+ if c[:values]&.any?
235
+ val_strs = if c[:values].is_a?(Array)
236
+ c[:values].select { |v| v.is_a?(Hash) }.map { |v| "#{v[:name]}:#{v[:type]}" }
237
+ elsif c[:values].is_a?(Hash)
238
+ c[:values].map { |k, v| "#{k}:#{v}" }
239
+ else
240
+ []
241
+ end
242
+ lines << "- **Values:** #{val_strs.join(', ')}" if val_strs.any?
243
+ end
244
+ lines << "- **Actions:** #{Array(c[:actions]).join(', ')}" if c[:actions]&.any?
230
245
  end
231
246
  lines << ""
232
247
  end
@@ -266,7 +281,9 @@ module RailsAiContext
266
281
 
267
282
  related = {}
268
283
  matched_models.each do |name, data|
284
+ next unless data.is_a?(Hash)
269
285
  (data[:associations] || []).each do |a|
286
+ next unless a.is_a?(Hash)
270
287
  related_name = a[:class_name] || a[:name].to_s.classify
271
288
  next if matched_models.key?(related_name)
272
289
  related[related_name] ||= []
@@ -286,7 +303,9 @@ module RailsAiContext
286
303
 
287
304
  concerns = {}
288
305
  matched_models.each do |_name, data|
306
+ next unless data.is_a?(Hash)
289
307
  (data[:concerns] || []).each do |c|
308
+ next unless c.is_a?(String)
290
309
  next if c.include?("::") || %w[Kernel JSON PP].include?(c)
291
310
  concerns[c] ||= 0
292
311
  concerns[c] += 1
@@ -297,6 +316,8 @@ module RailsAiContext
297
316
  lines << "## Concerns"
298
317
  concerns.sort.each { |name, count| lines << "- **#{name}** (used by #{count} model#{'s' if count > 1})" }
299
318
  lines << ""
319
+ rescue
320
+ nil
300
321
  end
301
322
 
302
323
  # --- AF13: Callback Chains ---
@@ -305,7 +326,9 @@ module RailsAiContext
305
326
 
306
327
  callbacks = []
307
328
  matched_models.each do |name, data|
329
+ next unless data.is_a?(Hash)
308
330
  (data[:callbacks] || {}).each do |type, methods|
331
+ next unless methods.is_a?(Array)
309
332
  methods.each { |m| callbacks << "#{name}: #{type} :#{m}" }
310
333
  end
311
334
  end
@@ -602,17 +602,16 @@ module RailsAiContext
602
602
  model_data[:associations]&.each { |a| valid << a[:name]; valid << a[:foreign_key] if a[:foreign_key] }
603
603
  valid.merge(%w[id _destroy created_at updated_at])
604
604
 
605
- # V1: Smarter JSONB skip only skip params matching JSON column names, check the rest
606
- json_column_names = table_data[:columns]
607
- &.select { |c| %w[jsonb json].include?(c[:type]) }
608
- &.map { |c| c[:name] }
609
- &.to_set || Set.new
605
+ # If model has JSONB/JSON columns, permitted params likely go INTO those columns
606
+ # (e.g. Cook permits :product_details which is stored inside intake JSONB)
607
+ # Skip the entire check — too many false positives otherwise
608
+ has_json_columns = table_data[:columns]&.any? { |c| %w[jsonb json].include?(c[:type]) }
609
+ return warnings if has_json_columns
610
610
 
611
611
  visitor.permit_calls.each do |pc|
612
612
  pc[:params].each do |param|
613
613
  next if param.end_with?("_attributes") # nested attributes
614
614
  next if valid.include?(param)
615
- next if json_column_names.include?(param) # param matches a JSON column, skip
616
615
  warnings << "permits :#{param} \u2014 not a column in #{table_name} table"
617
616
  end
618
617
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsAiContext
4
- VERSION = "1.3.0"
4
+ VERSION = "1.3.1"
5
5
  end
data/server.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
3
  "name": "io.github.crisnahine/rails-ai-context",
4
4
  "title": "Rails AI Context",
5
- "description": "Auto-expose Rails app structure to AI via MCP. Zero config, 14 read-only tools.",
5
+ "description": "Auto-expose Rails app structure to AI via MCP. Zero config, 15 read-only tools, design system extraction.",
6
6
  "repository": {
7
7
  "url": "https://github.com/crisnahine/rails-ai-context",
8
8
  "source": "github"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-ai-context
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - crisnahine
@@ -184,7 +184,6 @@ files:
184
184
  - CONTRIBUTING.md
185
185
  - LICENSE
186
186
  - README.md
187
- - ROADMAP.md
188
187
  - Rakefile
189
188
  - SECURITY.md
190
189
  - docs/GUIDE.md
data/ROADMAP.md DELETED
@@ -1,148 +0,0 @@
1
- # rails-ai-context — Bugs & Improvements Roadmap
2
-
3
- > Comprehensive list from 6 testing sessions, ~500+ MCP calls, 522 specs, verified on DailyContentChef (9 tables, 6 models, 18 controllers, 15 Stimulus controllers).
4
- > Current version: v1.2.1 (updated 2026-03-23)
5
-
6
- ---
7
-
8
- ## Open Bugs
9
-
10
- ### MCP Tools
11
-
12
- | # | Bug | Severity | Tool | Status |
13
- |---|-----|----------|------|--------|
14
- | B1 | `unless: :devise_controller?` not fully evaluated — OmniauthCallbacksController shows `authenticate_user!` | LOW | controllers | **FIXED v1.2.1** — evaluates condition at introspection time, removes filter for Devise controllers |
15
- | B2 | `self` appears in class methods list — Plan shows `self` as a class method alongside `free`, `pro`, `business` | LOW | model_details | Open |
16
-
17
- ### Rules Serializer (generated CLAUDE.md / rules files)
18
-
19
- | # | Bug | Severity | Status |
20
- |---|-----|----------|--------|
21
- | R1 | User methods list shows ~5 of 18 — missing concern + model-defined methods | MEDIUM | **FIXED v1.2.1** — source-defined methods prioritized, Devise methods filtered |
22
- | R3 | `visuals_needed` shown as `string` not `string[]` in rules | MEDIUM | **FIXED v1.2.1** — array columns now render as `type[]` |
23
- | R4 | payments missing `paymongo_checkout_id` and `paymongo_payment_id` columns in rules | MEDIUM | **FIXED v1.2.1** — external ID columns no longer hidden |
24
- | R5 | users missing `paymongo_customer_id` column in rules | MEDIUM | **FIXED v1.2.1** — same fix as R4 |
25
- | R6 | No column defaults shown in generated rules | MEDIUM | **FIXED v1.2.1** — defaults shown inline as `(=value)` |
26
-
27
- ---
28
-
29
- ## Improvements: `rails_analyze_feature`
30
-
31
- ### Tier 1 — Core (makes the tool 10x more useful)
32
-
33
- | # | Improvement | Description | Impact |
34
- |---|-------------|-------------|--------|
35
- | AF1 | **Services discovery** | Scan `app/services/` for classes matching the feature keyword. Show class name, line count, key method names. `feature:"cook"` → finds `ContentChefService`, `GeminiClient`, `OutputParser` | HIGH |
36
- | AF2 | **Jobs discovery** | Scan `app/jobs/` for matching classes. Show queue name, retry config, what service it calls. `feature:"cook"` → finds `CookJob` (queue: default, retries: 3, calls ContentChefService) | HIGH |
37
- | AF3 | **Views + partials discovery** | List matching views with line counts, partial renders, and Stimulus controller references. `feature:"cook"` → shows `cooks/show.html.erb (61 lines) renders: cooks/output, cooks/loading stimulus: cook-status, share` | HIGH |
38
- | AF4 | **Stimulus controllers discovery** | Match Stimulus controllers by name. Show targets, values, actions. `feature:"cook"` → finds `cook_status` controller with `cookId` value and `checkTimeout` action | HIGH |
39
- | AF5 | **Test files discovery** | List matching test files with test counts. `feature:"cook"` → shows `test/models/cook_test.rb (13 tests)`, `test/controllers/cooks_controller_test.rb (21 tests)` | HIGH |
40
-
41
- ### Tier 2 — Cross-cutting intelligence
42
-
43
- | # | Improvement | Description | Impact |
44
- |---|-------------|-------------|--------|
45
- | AF6 | **Related models via associations** | Show models connected through `belongs_to`, `has_many`. `feature:"cook"` → "Related: User (owner), BrandProfile (optional), CookShare (shares)" | MEDIUM |
46
- | AF7 | **Execution flow graph** | Trace the full request lifecycle: controller action → authorization check → model operation → job enqueue → service call → external API → broadcast. No other tool does this. | MEDIUM |
47
- | AF8 | **Permission/authorization mapping** | Map which concern methods guard which actions. `can_cook?` guards `CooksController#create`, `can_use_bonus_modes?` guards `Bonus::BaseController` | MEDIUM |
48
- | AF9 | **Environment dependencies** | Detect ENV vars referenced by the feature. `feature:"cook"` → requires `GEMINI_API_KEY`, Sidekiq running, Redis connected | MEDIUM |
49
- | AF10 | **Channel/websocket discovery** | Find `turbo_stream_from` and Action Cable subscriptions. `feature:"cook"` → uses `turbo_stream_from "cook_#{id}"` for real-time output | MEDIUM |
50
-
51
- ### Tier 3 — Agent workflow optimization
52
-
53
- | # | Improvement | Description | Impact |
54
- |---|-------------|-------------|--------|
55
- | AF11 | **Mailer/notification discovery** | Scan `app/mailers/` for matching classes and their delivery triggers | LOW |
56
- | AF12 | **Concern tracing** | When a feature uses concerns, list which concerns and their methods. `feature:"User"` → PlanLimitable adds 12 methods | LOW |
57
- | AF13 | **Callback chains** | Show before/after hooks that fire. `feature:"brand"` → `before_save :ensure_single_default` on BrandProfile | LOW |
58
- | AF14 | **"How to extend" hints** | Based on existing patterns, suggest where to add a new action, new validation, new partial. "To add a new cook mode: add to MODES constant (line 7), add view in bonus/" | LOW |
59
-
60
- ---
61
-
62
- ## Improvements: `rails_get_design_system`
63
-
64
- ### Tier 1 — Missing component patterns
65
-
66
- | # | Improvement | Description | Impact |
67
- |---|-------------|-------------|--------|
68
- | DS1 | **Modal pattern** | Extract overlay + card pattern from `_share_modal.html.erb`. Show: `fixed inset-0 bg-black/50 z-40` overlay + `bg-white rounded-2xl shadow-lg max-w-md w-full p-6` card | HIGH |
69
- | DS2 | **Badge/tag pattern** | Extract from mode badges: `text-xs font-medium px-2.5 py-1 rounded-full bg-{color}-100 text-{color}-700`. Show color variants (indigo, green, yellow, red) | HIGH |
70
- | DS3 | **Status indicator pattern** | Extract from `_status_badge.html.erb`. Show as a reusable shared partial reference: `render "shared/status_badge", cook: cook` | HIGH |
71
- | DS4 | **Flash/toast patterns** | Extract from `_flash.html.erb`. Show success (`bg-green-50 border-green-200 text-green-700`), error (`bg-red-50 border-red-200 text-red-700`), notice variants | HIGH |
72
- | DS5 | **List item pattern** | Extract the repeating card-per-item layout from cook index: `bg-white rounded-xl p-5 shadow-sm border border-gray-100 flex items-center justify-between gap-4` | HIGH |
73
- | DS6 | **Secondary button** | Extract: `bg-gray-100 text-gray-700 px-4 py-2 rounded-xl text-sm font-semibold hover:bg-gray-200 transition cursor-pointer`. Currently only primary + danger listed | MEDIUM |
74
- | DS7 | **Shared partials section** | List all `app/views/shared/` partials with one-line descriptions. Agents should reuse these before creating new markup: `_flash.html.erb`, `_navbar.html.erb`, `_status_badge.html.erb`, `_upgrade_nudge.html.erb` | MEDIUM |
75
-
76
- ### Tier 2 — Decision guidance
77
-
78
- | # | Improvement | Description | Impact |
79
- |---|-------------|-------------|--------|
80
- | DS8 | **"When to use what" decision guide** | Not just class strings but rules: "Page needs a form? → Copy Form Page example. Need confirmation? → `data: { turbo_confirm: 'message' }`. Showing status? → `render 'shared/status_badge'`" | HIGH |
81
- | DS9 | **Loading/spinner pattern** | Extract from `_loading.html.erb`: `animate-spin` emoji + progress bar (`bg-orange-500 h-2 rounded-full animate-pulse`) | MEDIUM |
82
- | DS10 | **Confirmation dialog convention** | Document the Turbo Confirm pattern: `data: { turbo_confirm: "Are you sure?" }` on `button_to` for destructive actions | MEDIUM |
83
- | DS11 | **Form error pattern** | Show what validation errors look like: field highlighting, error message placement, `field_with_errors` wrapper behavior | MEDIUM |
84
- | DS12 | **Spacing system rules** | Explain WHEN to use each spacing: `space-y-3` for list items, `space-y-4` for form fields, `space-y-6` for form sections, `gap-2` for button groups, `mb-6` for section separators | LOW |
85
-
86
- ### Tier 3 — Framework adaptability
87
-
88
- | # | Improvement | Description | Impact |
89
- |---|-------------|-------------|--------|
90
- | DS13 | **Auto-detect CSS framework** | Detect Tailwind vs Bootstrap vs custom CSS/Sass. Adapt extraction strategy per framework. Currently hardcoded for Tailwind — broken for all other setups | HIGH |
91
- | DS14 | **Bootstrap support** | Scan ERB for Bootstrap classes (`btn-primary`, `card`, `modal`, `form-control`). Parse `_variables.scss` for custom theme. Show Bootstrap component examples from actual views | HIGH (for Bootstrap apps) |
92
- | DS15 | **Custom CSS/Sass support** | Parse `.scss/.css` files for class definitions. Group by file (buttons.scss → Button patterns). Detect BEM naming. Show CSS custom properties (`--color-primary`) | HIGH (for custom apps) |
93
- | DS16 | **Parse Tailwind `@apply` directives** | If app has `@apply` rules in CSS, extract those as named component classes | MEDIUM |
94
- | DS17 | **Detect DaisyUI / Flowbite / Headless UI** | If Tailwind plugin libraries are installed, include their component patterns alongside raw Tailwind | MEDIUM |
95
- | DS18 | **Parse `tailwind.config.js` custom theme** | Extract custom colors, fonts, spacing from the config file. Show `primary: '#FF6B00'` if customized | MEDIUM |
96
- | DS19 | **Animation/transition inventory** | List all `transition`, `animate-*`, `duration-*` patterns with usage context | LOW |
97
- | DS20 | **Icon size conventions** | Document when to use which size: `w-3.5 h-3.5` (inline with text), `w-4 h-4` (buttons), `w-5 h-5` (standalone), `w-10 h-10` (feature icons) | LOW |
98
- | DS21 | **Remove oklch noise from summary** | Token colors (oklch values) waste tokens in summary. Move to `detail:"full"` only. Summary should show Tailwind class names only | LOW |
99
-
100
- ---
101
-
102
- ## Improvements: Rules Serializer
103
-
104
- | # | Improvement | Description | Impact |
105
- |---|-------------|-------------|--------|
106
- | RS1 | **Include all concern methods** | User methods list should include all PlanLimitable methods (12+), not just 5 | HIGH — partially fixed in v1.2.1 (source methods prioritized), full concern method extraction still open |
107
- | RS2 | **Detect array columns** | Show `visuals_needed:string[]` not `visuals_needed:string` | ~~MEDIUM~~ **FIXED v1.2.1** |
108
- | RS3 | **Include all non-system columns** | payments should show `paymongo_checkout_id`, `paymongo_payment_id`. users should show `paymongo_customer_id` | ~~MEDIUM~~ **FIXED v1.2.1** |
109
- | RS4 | **Show column defaults** | Inline defaults: `mode:string(default:"standard")`, `status:string(default:"pending")` | ~~MEDIUM~~ **FIXED v1.2.1** |
110
-
111
- ---
112
-
113
- ## Improvements: `rails_validate`
114
-
115
- | # | Improvement | Description | Impact |
116
- |---|-------------|-------------|--------|
117
- | V1 | **Smarter JSONB strong params skip** | Currently skips ALL params check for models with ANY JSONB column. Could be smarter: only skip params matching JSONB column names, check the rest | LOW |
118
- | V2 | **Route-action check suggests fix** | When `show` action missing but route exists, suggest: "Add `def show; end` to BrandProfilesController or remove `show` from `resources :brand_profiles`" | LOW |
119
-
120
- ---
121
-
122
- ## Improvements: `rails_get_model_details`
123
-
124
- | # | Improvement | Description | Impact |
125
- |---|-------------|-------------|--------|
126
- | MD1 | **Filter `self` from class methods** | Plan shows `self` as a class method — should be filtered out | LOW |
127
-
128
- ---
129
-
130
- ## Summary
131
-
132
- | Category | Total | Fixed | Open | Tier 1 (HIGH) | Tier 2 (MEDIUM) | Tier 3 (LOW) |
133
- |----------|-------|-------|------|--------------|-----------------|--------------|
134
- | Open Bugs | 7 | 6 | 1 | 0 | 0 | 1 (B2) |
135
- | analyze_feature | 14 | 0 | 14 | 5 | 5 | 4 |
136
- | design_system | 21 | 0 | 21 | 9 | 6 | 6 |
137
- | Rules serializer | 4 | 3 | 1 | 1 (RS1 partial) | 0 | 0 |
138
- | validate | 2 | 0 | 2 | 0 | 0 | 2 |
139
- | model_details | 1 | 0 | 1 | 0 | 0 | 1 |
140
- | **Total** | **49** | **9** | **40** | **15** | **11** | **14** |
141
-
142
- ### Killer differentiators (no other tool does these)
143
-
144
- 1. **Execution flow graph** (AF7) — trace a full request from HTTP to database to broadcast in one call
145
- 2. **"When to use what" decision guide** (DS8) — not just patterns but rules for choosing the right one
146
- 3. **Auto-detect CSS framework** (DS13-DS15) — works for Tailwind, Bootstrap, custom CSS, any Rails app
147
- 4. **Services + Jobs + Views + Tests in feature analysis** (AF1-AF5) — full-stack feature discovery in one call
148
- 5. **Environment dependency detection** (AF9) — know what needs to be running before you touch a feature