rails-ai-context 5.8.1 → 5.9.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +136 -20
- data/README.md +14 -14
- data/Rakefile +38 -0
- data/demo/demo-trace.tape +2 -2
- data/demo/demo.tape +1 -1
- data/docs/ARCHITECTURE.md +1 -1
- data/docs/CLI.md +2 -2
- data/docs/FAQ.md +2 -2
- data/docs/GUIDE.md +25 -25
- data/docs/QUICKSTART.md +1 -1
- data/docs/RECIPES.md +16 -16
- data/docs/SETUP.md +5 -4
- data/docs/TOOLS.md +1 -1
- data/exe/rails-ai-context +137 -2
- data/lib/generators/rails_ai_context/install/install_generator.rb +85 -2
- data/lib/rails_ai_context/doctor.rb +5 -2
- data/lib/rails_ai_context/introspectors/job_introspector.rb +2 -1
- data/lib/rails_ai_context/serializers/claude_rules_serializer.rb +1 -1
- data/lib/rails_ai_context/serializers/claude_serializer.rb +1 -77
- data/lib/rails_ai_context/serializers/compact_serializer_helper.rb +81 -0
- data/lib/rails_ai_context/serializers/context_file_serializer.rb +15 -34
- data/lib/rails_ai_context/serializers/cursor_rules_serializer.rb +45 -8
- data/lib/rails_ai_context/serializers/section_marker_writer.rb +63 -0
- data/lib/rails_ai_context/serializers/tool_guide_helper.rb +16 -16
- data/lib/rails_ai_context/tasks/rails_ai_context.rake +136 -3
- data/lib/rails_ai_context/tools/analyze_feature.rb +28 -18
- data/lib/rails_ai_context/tools/base_tool.rb +47 -1
- data/lib/rails_ai_context/tools/diagnose.rb +2 -2
- data/lib/rails_ai_context/tools/generate_test.rb +7 -6
- data/lib/rails_ai_context/tools/get_concern.rb +69 -10
- data/lib/rails_ai_context/tools/get_context.rb +5 -5
- data/lib/rails_ai_context/tools/get_controllers.rb +2 -2
- data/lib/rails_ai_context/tools/get_conventions.rb +15 -11
- data/lib/rails_ai_context/tools/get_edit_context.rb +2 -2
- data/lib/rails_ai_context/tools/get_env.rb +7 -5
- data/lib/rails_ai_context/tools/get_helper_methods.rb +21 -12
- data/lib/rails_ai_context/tools/get_job_pattern.rb +21 -13
- data/lib/rails_ai_context/tools/get_partial_interface.rb +8 -0
- data/lib/rails_ai_context/tools/get_routes.rb +1 -1
- data/lib/rails_ai_context/tools/get_schema.rb +1 -1
- data/lib/rails_ai_context/tools/get_service_pattern.rb +17 -9
- data/lib/rails_ai_context/tools/get_stimulus.rb +7 -4
- data/lib/rails_ai_context/tools/get_test_info.rb +13 -11
- data/lib/rails_ai_context/tools/get_turbo_map.rb +19 -15
- data/lib/rails_ai_context/tools/get_view.rb +61 -9
- data/lib/rails_ai_context/tools/migration_advisor.rb +1 -1
- data/lib/rails_ai_context/tools/onboard.rb +2 -1
- data/lib/rails_ai_context/tools/query.rb +29 -1
- data/lib/rails_ai_context/tools/read_logs.rb +18 -4
- data/lib/rails_ai_context/tools/search_code.rb +3 -3
- data/lib/rails_ai_context/tools/validate.rb +4 -4
- data/lib/rails_ai_context/version.rb +1 -1
- data/lib/rails_ai_context/vfs.rb +9 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5f300193f1fb692df6f1404e884f9efddbafc85b2cadee89adaa995f49e69ca0
|
|
4
|
+
data.tar.gz: befb6b7b12702fe0ff805786d1e7628d1c2cca0fd1a7f85d7a655a0521bde69a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 95950aab08d9547799c7271d838cb145deee30a7b29930ffc8bbe2c83ff8b130a1ecb8eb53722d025c91658d7ea9365c5a5bb81aafce796aa51b28c91b0980e8
|
|
7
|
+
data.tar.gz: 43a6e75ff67650e5ab91b95cab532fc9a09fa1c60e52728825a145101fcdd54e2aabb59d250fcdb5c3eede77309b9c6030023f9ba3857a45dc9b1824031790c0
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,122 @@ 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
|
+
## [5.9.0] — 2026-04-16
|
|
9
|
+
|
|
10
|
+
### Fixed — Cursor chat agent didn't detect rules
|
|
11
|
+
|
|
12
|
+
Real user report during release QA: the Cursor IDE's chat agent didn't pick up rules written only as `.cursor/rules/*.mdc`, even when the rule declared `alwaysApply: true`. Cursor has **two** rule systems and the chat-agent composition path still consults the legacy `.cursorrules` file in many current builds.
|
|
13
|
+
|
|
14
|
+
`CursorRulesSerializer` now writes **both**: `.cursor/rules/*.mdc` (newer format with frontmatter / glob scoping / agent-requested triggers) AND a plain-text `.cursorrules` at the project root (legacy fallback, parsed verbatim by every Cursor build). Newer clients read the mdc files; older / chat-mode clients read `.cursorrules`. No behavior change for users who already relied on the mdc format.
|
|
15
|
+
|
|
16
|
+
The `.cursorrules` content goes through the **same** `CompactSerializerHelper#render_compact_rules` pipeline as `CLAUDE.md`, so both files convey identical project context — header, stack overview, key models, gems, architecture, commands, rules, and the MCP tool guide. Drift between the two files is no longer possible short of a manual divergence (regression spec enforces parity).
|
|
17
|
+
|
|
18
|
+
`.cursorrules` is **wrapped in `<!-- BEGIN/END rails-ai-context -->` markers** via the new `SectionMarkerWriter` module — same convention as `CLAUDE.md`, `AGENTS.md`, and `.github/copilot-instructions.md`. Pre-existing user content above or below the marker block survives every `rails ai:context` regeneration. Three regression specs cover the three branches: no-file → write markers; existing-without-markers → prepend gem block; existing-with-markers → replace only the gem block.
|
|
19
|
+
|
|
20
|
+
`FORMAT_PATHS[:cursor]` in the install generator now includes `.cursorrules` so re-install cleanup covers both files when a user removes Cursor from their selection. Regression specs added in `cursor_rules_serializer_spec.rb` and `in_gemfile_install_spec.rb` (e2e) verify both files are produced and the legacy file is plain text without frontmatter.
|
|
21
|
+
|
|
22
|
+
### Fixed — Round 3 follow-ups (post-quad-agent review)
|
|
23
|
+
|
|
24
|
+
- **`safe_glob_realpath` rescue widened.** Previously rescued only `Errno::ENOENT` and `Errno::EACCES`. Circular symlink chains (think `node_modules/@scope/*` cycles or developer-crafted loops) raise `Errno::ELOOP`; path components exceeding `NAME_MAX` raise `Errno::ENAMETOOLONG`. Both now rescued — return `nil` to skip the entry — preserving the CLAUDE.md invariant that every introspector wraps errors.
|
|
25
|
+
|
|
26
|
+
- **Install generator `CONFIG_SECTIONS` gained 3 sections.** Several user-facing config options existed in `Configuration::YAML_KEYS` but had no commented-out template line in the generated `config/initializers/rails_ai_context.rb`. Added "Database Query Tool" (`query_timeout`, `query_row_limit`, `query_redacted_columns`, `allow_query_in_production`), "Log Reading" (`log_lines`), and "Hydration" (`hydration_enabled`, `hydration_max_hints`) sections so in-Gemfile installs surface every supported knob.
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- **`preset` command** — composite multi-tool workflows from CLI and rake. `rails ai:preset[architecture]` runs `analyze_feature` + `dependency_graph` + `performance_check` in one call. Also: `debugging` (logs + review + validate) and `migration` (schema + migration_advisor + validate). Available via both `rails-ai-context preset architecture` and `rails 'ai:preset[architecture]'`.
|
|
31
|
+
|
|
32
|
+
- **`facts` command** — concise schema facts summary. `rails ai:facts` / `rails-ai-context facts` prints tables with column/index/FK counts, model associations, key dependencies, and architecture patterns. Single command replaces 3+ MCP tool calls for quick context loading.
|
|
33
|
+
|
|
34
|
+
- **Validation pre-commit hook** — optional during `rails generate rails_ai_context:install`. Prompts to install a `.git/hooks/pre-commit` hook that runs `rails ai:tool[validate]` on staged `.rb` and `.erb` files. Catches hallucinated columns and schema drift before commit. Respects existing hooks and `--no-verify`.
|
|
35
|
+
|
|
36
|
+
### Added — E2E harness (`spec/e2e/`)
|
|
37
|
+
|
|
38
|
+
Real `rails new` → install → exercise → teardown against a fresh Rails application in a tmpdir. Covers the three install paths documented in CLAUDE.md #36, every CLI tool, the install generator, all 5 AI-client config files, and the MCP JSON-RPC protocol over both stdio and HTTP transports. Excluded from the default `rspec` run — opt-in via `E2E=1` or the new rake tasks.
|
|
39
|
+
|
|
40
|
+
- **`spec/e2e/in_gemfile_install_spec.rb`** — Path A (Gemfile entry + `rails generate rails_ai_context:install`). Verifies generator idempotency, per-AI-client config file validity, every built-in tool callable via both `bin/rails ai:tool[name]` and `bundle exec rails-ai-context tool name`, plus the `version`/`doctor`/`inspect` subcommands.
|
|
41
|
+
|
|
42
|
+
- **`spec/e2e/standalone_install_spec.rb`** — Path B (`gem install rails-ai-context` into an isolated GEM_HOME, no Gemfile entry, then `rails-ai-context init`). Verifies the Bundler-stripped `$LOAD_PATH` restoration logic described in CLAUDE.md #33 actually works on a real app.
|
|
43
|
+
|
|
44
|
+
- **`spec/e2e/zero_config_install_spec.rb`** — Path C (gem install, no init, no generator). Verifies the CLI works from pure defaults against any Rails app without any project-side setup.
|
|
45
|
+
|
|
46
|
+
- **`spec/e2e/mcp_stdio_protocol_spec.rb`** — spawns `rails-ai-context serve` as a subprocess and walks the full JSON-RPC 2.0 handshake: `initialize` → `notifications/initialized` → `tools/list` → `tools/call`. Verifies every registered built-in tool is advertised in `tools/list` with a rails_-prefixed name, description, and inputSchema.
|
|
47
|
+
|
|
48
|
+
- **`spec/e2e/mcp_http_protocol_spec.rb`** — spawns `rails-ai-context serve --transport http` on a random free port and sends `Net::HTTP` POST requests with JSON-RPC payloads. Verifies the HTTP transport returns the same tool registry and tool-call responses as stdio. Handles the Streamable HTTP requirements: `Accept: application/json, text/event-stream` header + `Mcp-Session-Id` round-trip from initialize.
|
|
49
|
+
|
|
50
|
+
- **`spec/e2e/empty_app_spec.rb`** — every built-in tool must handle a Rails app with no scaffolds, no models, no custom routes. Catches "tool crashes when introspecting an empty greenfield app" — the moment a developer is most likely to install rails-ai-context.
|
|
51
|
+
|
|
52
|
+
- **`spec/e2e/tool_edge_cases_spec.rb`** — malformed CLI inputs: unknown tool name, unknown parameter, missing required parameter, oversized string (10 KB), invalid enum value, fuzzy-match recovery, nonexistent target. Each case must produce structured user-facing errors, never an unhandled exception or signal.
|
|
53
|
+
|
|
54
|
+
- **`spec/e2e/concurrent_mcp_spec.rb`** — two parallel `rails-ai-context serve` subprocesses against the same Rails app. Verifies independent initialize responses, identical tool registries, and that simultaneous `tools/call` invocations don't cross-talk (response id matches request id per client).
|
|
55
|
+
|
|
56
|
+
- **`spec/e2e/postgres_install_spec.rb`** — Postgres adapter coverage for the `rails_query` tool's adapter-specific code paths: `SET TRANSACTION READ ONLY`, `BLOCKED_FUNCTIONS` regex against `pg_read_file`, `dblink`, `COPY ... PROGRAM`, and DDL rejection. Skipped locally unless `TEST_POSTGRES=1`; runs unconditionally in CI which spins up a Postgres 16 service container.
|
|
57
|
+
|
|
58
|
+
- **`spec/e2e/massive_app_spec.rb`** — 1500-model stress test. Programmatically generates a single migration with 1500 `create_table` statements and 1500 corresponding `ApplicationRecord` subclass files (rails-g-scaffold × 1500 would take 30+ min; direct file writes take seconds). Runs representative tools (`schema`, `model_details`, `routes`, `context`, `onboard`, `analyze_feature`, `get_turbo_map`, `get_env`) against the massive fixture and asserts: no signal, exit < 2, stdout non-empty, response size < 2 MB (tools must truncate — uncapped output overwhelms AI client context). Also verifies `rails_get_schema --table thing_0750s` finds a table in the middle of the range, proving schema introspection walks beyond the first page.
|
|
59
|
+
|
|
60
|
+
Rake tasks: `bundle exec rake e2e` (full), `rake e2e:in_gemfile`, `rake e2e:standalone`, `rake e2e:zero_config`, `rake e2e:mcp`.
|
|
61
|
+
|
|
62
|
+
CI: `.github/workflows/e2e.yml` runs on push to main + workflow_dispatch (separate from `ci.yml` so the 30-min job doesn't fail-stop the per-commit matrix). Matrix covers Ruby 3.3 + 3.4 across Rails 7.1, 7.2, 8.0, 8.1, and includes a Postgres 16 service container so the SQL-query and adapter-specific code paths are exercised on every push.
|
|
63
|
+
|
|
64
|
+
### Fixed — Security Hardening (Round 3)
|
|
65
|
+
|
|
66
|
+
Pre-release audit of **every** `Dir.glob` call site across the 38 tools. The 5-rule file-read pattern documented in CLAUDE.md was enforced on caller-supplied paths, but glob-sourced paths were reading file content without the same hardening. A symlink pre-planted inside `app/services/`, `app/jobs/`, `app/helpers/`, `app/models/`, `app/controllers/`, `app/views/`, or `app/` (pointing at `config/master.key`) would have leaked secret contents through tool output.
|
|
67
|
+
|
|
68
|
+
- **`BaseTool.safe_glob_realpath` + `BaseTool.safe_glob`** added as shared helpers. Every glob-sourced file read now passes through this filter: realpath + separator-aware containment + `sensitive_file?` recheck on the realpath. Broken symlinks, sibling-directory bypasses, and sensitive-pattern matches return `nil` and are skipped.
|
|
69
|
+
|
|
70
|
+
- **`get_service_pattern`, `get_job_pattern`, `get_helper_methods`** — glob+read on `app/services/`, `app/jobs/`, `app/helpers/` plus nested `find_callers` / `find_enqueuers` / `find_view_references` / `detect_framework_helpers`. All hardened.
|
|
71
|
+
|
|
72
|
+
- **`analyze_feature`** — 10 glob sites across `discover_services`, `discover_jobs`, `discover_views`, `discover_tests`, `discover_test_gaps`, `discover_channels`, `discover_mailers`, `discover_env_dependencies`. All hardened.
|
|
73
|
+
|
|
74
|
+
- **`get_conventions`** — glob+read on controllers (convention detection), services (listing), locales, controllers (UI-language detection), tests (pattern detection). All hardened.
|
|
75
|
+
|
|
76
|
+
- **`get_turbo_map`** — glob+read on models, controllers/services/jobs/channels, and two view scans. All hardened.
|
|
77
|
+
|
|
78
|
+
- **`get_env`** — glob+read on `app/config/lib` for ENV scans, `app/` for HTTP-client detection, and `app/config/lib` for prefix-matched ENV vars. All hardened. Removed redundant pre-realpath `sensitive_file?` now that `safe_glob` checks post-realpath.
|
|
79
|
+
|
|
80
|
+
- **`get_test_info`** — glob+read on `test/**/*_test.rb` for Devise detection, `test/fixtures` and `spec/fixtures` for fixture parsing. Hardened.
|
|
81
|
+
|
|
82
|
+
- **`generate_test`** — glob+read on `spec/**/*_spec.rb` or `test/**/*_test.rb` for pattern detection. Hardened.
|
|
83
|
+
|
|
84
|
+
- **`get_stimulus`** — glob+read on `app/views/**/*.{erb,html.erb}` for `data-controller` usage. Hardened.
|
|
85
|
+
|
|
86
|
+
- **`onboard`** — glob of `app/services/` for service name extraction (basename only). Hardened for consistency even though no content is read.
|
|
87
|
+
|
|
88
|
+
- **`search_code`** (ruby-fallback path) — the pre-realpath `sensitive_file?` check did not catch a symlink `app/models/innocent.rb → config/master.key` because the relative path looked safe. Now goes through `safe_glob` which rechecks on the realpath.
|
|
89
|
+
|
|
90
|
+
- **`job_introspector.rb:205`** — bare `rescue` (catching `Exception`, including `Interrupt`/`SystemExit`) replaced with project-standard `rescue => e` + DEBUG logging guard.
|
|
91
|
+
|
|
92
|
+
- **14 new regression specs** covering every newly-hardened tool with a symlink-to-master.key PoC + 5 edge cases for the `safe_glob_realpath` helper (sibling bypass, broken symlinks, sensitive realpath, separator awareness, in-tree passthrough).
|
|
93
|
+
|
|
94
|
+
### Fixed — Security Hardening (Round 2)
|
|
95
|
+
|
|
96
|
+
Eleven additional vulnerabilities and defense-in-depth gaps found by multi-round adversarial code review. All discovered post-v5.8.1 — **users on 5.8.x should upgrade**.
|
|
97
|
+
|
|
98
|
+
- **MySQL executable-comment bypass of `BLOCKED_FUNCTIONS`.** `strip_sql_comments` stripped `/*! ... */` (MySQL version-conditional comments) along with regular block comments. MySQL *executes* content inside `/*! ... */`, so `SELECT /*!50000 LOAD_FILE('/etc/passwd') */ AS x` passed all validation. **Fix:** unwraps executable comments (preserves inner content for checker visibility) before the block-comment strip. Belt-and-suspenders: also runs `BLOCKED_FUNCTIONS` against the raw SQL before any stripping.
|
|
99
|
+
|
|
100
|
+
- **`execute_explain` bypassed READ ONLY transaction and statement timeout.** The EXPLAIN path called `conn.select_all(explain_sql)` directly instead of routing through `execute_postgresql`/`execute_mysql`/`execute_sqlite`. PostgreSQL `EXPLAIN (FORMAT JSON, ANALYZE)` actually executes the query plan — an attacker could hold a DB connection indefinitely and bypass the read-only guard. **Fix:** routes through adapter-specific safety wrappers.
|
|
101
|
+
|
|
102
|
+
- **`read_logs` C1 sibling-directory bypass.** Bare `real.start_with?(File.realpath(root))` matched `/var/app/myapp_evil` against `/var/app/myapp`. **Fix:** separator-aware containment (`real == base || real.start_with?(base + File::SEPARATOR)`).
|
|
103
|
+
|
|
104
|
+
- **`read_logs` TOCTOU window.** Resolved the realpath for the containment check, then opened the original `path` for reading. Symlink swap between check and open leaked arbitrary files. **Fix:** returns and reads from the realpath.
|
|
105
|
+
|
|
106
|
+
- **`read_logs` missing post-realpath sensitive recheck.** A symlink `log/credentials.log -> ../config/master.key` resolves to a path still under Rails.root, passing containment. Without `sensitive_file?` on the realpath, `tail_file` read the secret. **Fix:** added post-realpath `sensitive_file?` recheck.
|
|
107
|
+
|
|
108
|
+
- **VFS `resolve_view` existence-oracle side channel.** `File.exist?` ran before `sensitive_file?`, so two distinct error messages ("View not found" vs "sensitive file") revealed whether `.env` / `master.key` existed inside `app/views/`. **Fix:** early `sensitive_file?` check before any filesystem stat.
|
|
109
|
+
|
|
110
|
+
- **`get_partial_interface` existence-oracle side channel.** `candidates.find { |c| File.exist?(c) }` stat'd candidates before any sensitive check on the caller-supplied `partial` string. Same oracle as the VFS fix. **Fix:** early `sensitive_file?` check in `call`.
|
|
111
|
+
|
|
112
|
+
- **`get_view` `list_layouts` missing all security rules.** Iterated `Dir.glob` results with no realpath containment, no sensitive recheck, and no size gate. A symlink `layouts/leak.key -> ../../config/master.key` leaked secrets in the `full` detail branch. **Fix:** full 5-rule file-reading pattern per file.
|
|
113
|
+
|
|
114
|
+
- **`get_view` `read_view_content` missing all security rules.** Called `SafeFile.read` after a bare `File.exist?` with no containment, no sensitive recheck, and no size cap. **Fix:** full 5-rule file-reading pattern with `max_file_size` gate.
|
|
115
|
+
|
|
116
|
+
- **`get_concern` `show_concern` path traversal.** `name.underscore` does not sanitize `../`, so `name: "../../config/initializers/devise"` read arbitrary `.rb` files under Rails.root. The proposed fix in the IDOR variant would have been a security downgrade. **Fix:** early traversal/null-byte/absolute-path rejection, early `sensitive_file?`, per-candidate realpath + separator containment, post-realpath sensitive recheck.
|
|
117
|
+
|
|
118
|
+
- **`get_concern` `list_concerns` symlink escape.** `Dir.glob` results passed to `SafeFile.read` with no realpath containment or sensitive recheck. **Fix:** per-file 5-rule pattern.
|
|
119
|
+
|
|
120
|
+
### Changed
|
|
121
|
+
|
|
122
|
+
- All documentation examples, tool descriptions, code comments, and test fixtures now use generic Rails terminology (`PostsController`, `publishable?`, `posts/index.html.erb`) instead of app-specific references. Affects README, GUIDE, CLI, RECIPES docs, tool_guide_helper serializer, 6 MCP tool description strings, CHANGELOG, demo scripts, and 3 spec files.
|
|
123
|
+
|
|
8
124
|
## [5.8.1] — 2026-04-15
|
|
9
125
|
|
|
10
126
|
### Fixed — Security Hardening
|
|
@@ -628,11 +744,11 @@ AI assistants that consume pre-digested summaries produce worse output than AI t
|
|
|
628
744
|
- `analyze_feature` with nonexistent feature — returns clean "no match" instead of scaffolded empty sections
|
|
629
745
|
- `migration_advisor` crash on empty/invalid action — now validates with "Did you mean?" suggestions
|
|
630
746
|
- `migration_advisor` generates broken SQL with empty table/column — now validates required params
|
|
631
|
-
- `migration_advisor` doesn't normalize table names — "
|
|
747
|
+
- `migration_advisor` doesn't normalize table names — "Post" now auto-resolves to "posts"
|
|
632
748
|
- `migration_advisor` no duplicate column/index detection — now warns on existing columns, indexes, and FKs
|
|
633
749
|
- `migration_advisor` no nonexistent column detection — now warns on remove/rename/change_type/add_index for missing columns
|
|
634
750
|
- `edit_context` "File not found" with no hint — now suggests full path with "Did you mean?"
|
|
635
|
-
- `performance_check` model filter fails for multi-word models — "
|
|
751
|
+
- `performance_check` model filter fails for multi-word models — "UserProfile" now resolves to "user_profiles"
|
|
636
752
|
- `performance_check` unknown model silently ignored — now returns "not found" with suggestions
|
|
637
753
|
- `turbo_map` stream filter misses dynamic broadcasts — multi-line call handling + snippet fallback + fuzzy prefix matching
|
|
638
754
|
- `turbo_map` controller filter misses job broadcasts — now includes broadcasts matching filtered subscriptions' streams
|
|
@@ -640,7 +756,7 @@ AI assistants that consume pre-digested summaries produce worse output than AI t
|
|
|
640
756
|
- `search_code` unknown match_type silently ignored — now returns error with valid values
|
|
641
757
|
- `validate` unknown level silently ignored — now returns error with valid values
|
|
642
758
|
- `get_view` no "Did you mean?" on wrong controller — now uses `find_closest_match`
|
|
643
|
-
- `get_context` plural model name ("
|
|
759
|
+
- `get_context` plural model name ("Posts") produces mixed output — now normalizes via singularize/classify, fails fast when not found
|
|
644
760
|
- `component_catalog` specific component returns generic "no components" — now acknowledges the input
|
|
645
761
|
- `stimulus` doesn't strip `_controller` suffix — now auto-strips for lookup
|
|
646
762
|
- `controller_introspector_spec` rate_limit test crashes on Rails 7.1 — split into source-parsing test (no class loading)
|
|
@@ -694,15 +810,15 @@ AI assistants that consume pre-digested summaries produce worse output than AI t
|
|
|
694
810
|
### Fixed
|
|
695
811
|
|
|
696
812
|
- **Consistent input normalization across all tools** — AI agents and humans can now use any casing or format and tools resolve correctly:
|
|
697
|
-
- `model=
|
|
698
|
-
- `table=
|
|
699
|
-
- `controller=
|
|
700
|
-
- `controller=
|
|
701
|
-
- `stimulus=
|
|
813
|
+
- `model=user_profile` (snake_case) now resolves to `UserProfile` via `.underscore` comparison in `get_model_details`.
|
|
814
|
+
- `table=Post` (model name) now resolves to `posts` table via `.underscore.pluralize` normalization in `get_schema`.
|
|
815
|
+
- `controller=PostsController` now works in `get_view` and `get_routes` — both strip `Controller`/`_controller` suffix consistently, matching `get_controllers` behavior.
|
|
816
|
+
- `controller=posts_controller` no longer leaves a trailing underscore in route matching.
|
|
817
|
+
- `stimulus=PostStatus` (PascalCase) now resolves to `post_status` via `.underscore` conversion in `get_stimulus`.
|
|
702
818
|
- `partial=_status_badge` (underscore-prefixed, no directory) now searches recursively across all view directories in `get_partial_interface`.
|
|
703
|
-
- `model=
|
|
704
|
-
- **Smarter fuzzy matching** — `BaseTool.find_closest_match` now prefers shortest substring match (so `
|
|
705
|
-
- **File path suggestions in validate** — `files=["
|
|
819
|
+
- `model=posts` (plural) now tries `.singularize` for test file lookup in `get_test_info`.
|
|
820
|
+
- **Smarter fuzzy matching** — `BaseTool.find_closest_match` now prefers shortest substring match (so `Post` suggests `posts`, not `post_comments`) and supports underscore/classify variant matching.
|
|
821
|
+
- **File path suggestions in validate** — `files=["post.rb"]` now suggests `app/models/post.rb` when the file isn't found at the given path.
|
|
706
822
|
- **Empty parameter validation** — `edit_context` now returns friendly messages for empty `file` or `near` parameters instead of hard errors.
|
|
707
823
|
|
|
708
824
|
## [3.0.1] — 2026-03-26
|
|
@@ -748,10 +864,10 @@ AI assistants that consume pre-digested summaries produce worse output than AI t
|
|
|
748
864
|
|
|
749
865
|
### Added
|
|
750
866
|
|
|
751
|
-
- **Orphaned table detection** — `get_schema` standard mode flags tables with no ActiveRecord model: "⚠ Orphaned tables: content_calendars,
|
|
867
|
+
- **Orphaned table detection** — `get_schema` standard mode flags tables with no ActiveRecord model: "⚠ Orphaned tables: content_calendars, post_comments"
|
|
752
868
|
- **Concern method source code** — `get_concern(name:"X", detail:"full")` shows method bodies inline, same pattern as callbacks tool.
|
|
753
869
|
- **analyze_feature: inherited filters** — shows `authenticate_user! (from ApplicationController)` in controller section.
|
|
754
|
-
- **analyze_feature: code-ready route helpers** — `
|
|
870
|
+
- **analyze_feature: code-ready route helpers** — `post_path(@record)`, `posts_path` inline with routes.
|
|
755
871
|
- **analyze_feature: service test gaps** — checks services for missing test files, not just models/controllers/jobs.
|
|
756
872
|
- **All 6 serializers updated** — Claude, Cursor, Copilot, Windsurf, OpenCode all document trace mode, concern source, orphaned tables, inherited filters.
|
|
757
873
|
|
|
@@ -875,9 +991,9 @@ AI assistants that consume pre-digested summaries produce worse output than AI t
|
|
|
875
991
|
- **Empty string defaults shown as `""`** — schema tool now renders `""` instead of a blank cell for empty string defaults. AI can distinguish "no default" from "empty string default".
|
|
876
992
|
- **Implicit belongs_to validations labeled** — `presence on user` from `belongs_to :user` now shows `_(implicit from belongs_to)_` and filters phantom `(message: required)` options.
|
|
877
993
|
- **Array columns shown as `type[]`** in generated rules — `string` columns with `array: true` now render as `string[]` in schema rules.
|
|
878
|
-
- **External ID columns no longer hidden** — columns like `
|
|
994
|
+
- **External ID columns no longer hidden** — columns like `stripe_checkout_id` and `stripe_payment_id` are now shown in schema rules. Only conventional Rails FK columns (matching a table name) are filtered.
|
|
879
995
|
- **Column defaults shown in generated rules** — columns with non-nil defaults now show `(=value)` inline.
|
|
880
|
-
- **`analyze_feature` matches models by table name and underscore form** — `feature:"share"` now finds `
|
|
996
|
+
- **`analyze_feature` matches models by table name and underscore form** — `feature:"share"` now finds `PostShare` (via `post_shares` table and `post_share` underscore form), not just exact model name substring.
|
|
881
997
|
|
|
882
998
|
## [1.2.0] — 2026-03-23
|
|
883
999
|
|
|
@@ -966,7 +1082,7 @@ AI assistants that consume pre-digested summaries produce worse output than AI t
|
|
|
966
1082
|
|
|
967
1083
|
- **Schema defaults always visible** — Null and Default columns always shown (NOT NULL marked bold). Previous token-saving logic accidentally hid critical migration data.
|
|
968
1084
|
- **Optional associations** — `belongs_to` with `optional: true` now shows `[optional]` flag.
|
|
969
|
-
- **Concern methods inline** — shows public methods from concern source files (e.g. `
|
|
1085
|
+
- **Concern methods inline** — shows public methods from concern source files (e.g. `Publishable — publishable?, publish!`).
|
|
970
1086
|
- **MCP tool error messages** — all tools now show available values on error/not-found for AI self-correction.
|
|
971
1087
|
|
|
972
1088
|
## [0.15.5] — 2026-03-22
|
|
@@ -986,8 +1102,8 @@ AI assistants that consume pre-digested summaries produce worse output than AI t
|
|
|
986
1102
|
|
|
987
1103
|
### Fixed
|
|
988
1104
|
|
|
989
|
-
- **View subfolder paths** — listings now show full relative paths (`
|
|
990
|
-
- **Controller flexible matching** — `"
|
|
1105
|
+
- **View subfolder paths** — listings now show full relative paths (`admin/comments/index.html.erb`) instead of just basenames.
|
|
1106
|
+
- **Controller flexible matching** — `"posts"`, `"PostsController"`, `"postscontroller"` all resolve (matches other tools' forgiving lookup).
|
|
991
1107
|
- **View path traversal** — explicit `..` and absolute path rejection before any filesystem operation.
|
|
992
1108
|
- **Schema case-insensitive** — table lookup now case-insensitive (matches models/routes/etc.).
|
|
993
1109
|
- **limit:0 silent empty** — uses default instead of returning empty results.
|
|
@@ -1080,7 +1196,7 @@ AI assistants that consume pre-digested summaries produce worse output than AI t
|
|
|
1080
1196
|
- **`app_only` filter for routes** — `rails_get_routes(app_only: true)` (default) hides internal Rails routes (Active Storage, Action Mailbox, Conductor).
|
|
1081
1197
|
- **Search context lines** — `rails_search_code(context_lines: 2)` adds surrounding lines to matches (passes `-C` to ripgrep).
|
|
1082
1198
|
- **Stimulus dash/underscore normalization** — Both `weekly-chart` and `weekly_chart` work for controller lookup. Output shows HTML `data-controller` attribute.
|
|
1083
|
-
- **Model public method signatures** — `rails_get_model_details(model: "
|
|
1199
|
+
- **Model public method signatures** — `rails_get_model_details(model: "Post")` shows method names with params from source, stopping at private boundary.
|
|
1084
1200
|
|
|
1085
1201
|
## [0.13.1] — 2026-03-20
|
|
1086
1202
|
|
|
@@ -1118,7 +1234,7 @@ AI assistants that consume pre-digested summaries produce worse output than AI t
|
|
|
1118
1234
|
- **Design Token Introspector** — auto-detects CSS framework and extracts tokens from Tailwind v3/v4, Bootstrap/Sass, plain CSS custom properties, Webpacker-era stylesheets, and ViewComponent sidecar CSS. Tested across 8 CSS setups. Added to standard preset.
|
|
1119
1235
|
- **`rails_get_edit_context` MCP tool** — purpose-built for surgical edits. Returns code around a match point with line numbers. Replaces the Read + Edit workflow with a single call.
|
|
1120
1236
|
- **Line numbers in action source** — `rails_get_controllers(action: "index")` now returns start/end line numbers for targeted editing.
|
|
1121
|
-
- **Model file structure** — `rails_get_model_details(model: "
|
|
1237
|
+
- **Model file structure** — `rails_get_model_details(model: "Post")` now returns line ranges for each section (associations, validations, scopes, etc.).
|
|
1122
1238
|
|
|
1123
1239
|
### Changed
|
|
1124
1240
|
|
data/README.md
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
<br>
|
|
22
22
|
[](https://github.com/crisnahine/rails-ai-context)
|
|
23
23
|
[](https://github.com/crisnahine/rails-ai-context)
|
|
24
|
-
[](https://github.com/crisnahine/rails-ai-context/actions)
|
|
25
25
|
[](LICENSE)
|
|
26
26
|
|
|
27
27
|
</div>
|
|
@@ -95,7 +95,7 @@ Real scenarios where AI goes sideways — and what it does instead with ground t
|
|
|
95
95
|
| Write tests for a new model | Scaffolds with FactoryBot | Detects your fixture-based suite and matches it |
|
|
96
96
|
| Fix a failing create action | Misses inherited `before_action :authenticate_user!` | Returns parent-controller filters inline with the action source |
|
|
97
97
|
| Build a dashboard page | Invents Tailwind classes from memory | Returns your actual button/card/alert patterns, copy-paste ready |
|
|
98
|
-
| Trace where `
|
|
98
|
+
| Trace where `publishable?` is used | Reads 6 files sequentially, still misses callers | Single call: definition + source + every caller + tests |
|
|
99
99
|
|
|
100
100
|
<details>
|
|
101
101
|
<summary><strong>Verify it on your own app</strong></summary>
|
|
@@ -139,7 +139,7 @@ rails ai:serve
|
|
|
139
139
|
```
|
|
140
140
|
|
|
141
141
|
```
|
|
142
|
-
→ rails_search_code(pattern: "
|
|
142
|
+
→ rails_search_code(pattern: "publishable?", match_type: "trace")
|
|
143
143
|
→ rails_get_schema(table: "users")
|
|
144
144
|
→ rails_analyze_feature(feature: "billing")
|
|
145
145
|
```
|
|
@@ -166,7 +166,7 @@ Native Rails controller transport. No separate process needed.
|
|
|
166
166
|
Same 38 tools, no server needed. Works in any terminal, any AI tool.
|
|
167
167
|
|
|
168
168
|
```bash
|
|
169
|
-
rails 'ai:tool[search_code]' pattern="
|
|
169
|
+
rails 'ai:tool[search_code]' pattern="publishable?" match_type=trace
|
|
170
170
|
rails 'ai:tool[schema]' table=users
|
|
171
171
|
rails 'ai:tool[analyze_feature]' feature=billing
|
|
172
172
|
```
|
|
@@ -203,19 +203,19 @@ AI sees `subscription_status` already exists. Checks the model, then generates a
|
|
|
203
203
|
</details>
|
|
204
204
|
|
|
205
205
|
<details>
|
|
206
|
-
<summary><strong>"Fix the broken
|
|
206
|
+
<summary><strong>"Fix the broken post creation flow"</strong></summary>
|
|
207
207
|
|
|
208
208
|
<br>
|
|
209
209
|
|
|
210
210
|
```bash
|
|
211
|
-
rails 'ai:tool[controllers]' controller=
|
|
211
|
+
rails 'ai:tool[controllers]' controller=PostsController action=create
|
|
212
212
|
```
|
|
213
213
|
```
|
|
214
|
-
#
|
|
214
|
+
# PostsController#create
|
|
215
215
|
|
|
216
|
-
Filters: before_action :authenticate_user!, before_action :
|
|
217
|
-
Strong params:
|
|
218
|
-
Renders: redirect_to @
|
|
216
|
+
Filters: before_action :authenticate_user!, before_action :set_post (only: show, edit)
|
|
217
|
+
Strong params: post_params → title, body, published_at
|
|
218
|
+
Renders: redirect_to @post | render :new
|
|
219
219
|
```
|
|
220
220
|
|
|
221
221
|
AI sees the inherited `authenticate_user!` filter, the actual strong params, and the render paths. No guessing.
|
|
@@ -288,7 +288,7 @@ Every tool is **read-only** and returns data verified against your actual app
|
|
|
288
288
|
| Tool | What it does |
|
|
289
289
|
|:-----|:------------|
|
|
290
290
|
| `get_controllers` | Actions + inherited filters + render map + strong params |
|
|
291
|
-
| `get_routes` | Code-ready helpers (`
|
|
291
|
+
| `get_routes` | Code-ready helpers (`post_path(@record)`) + required params |
|
|
292
292
|
|
|
293
293
|
</details>
|
|
294
294
|
|
|
@@ -376,7 +376,7 @@ Plus 9 static resources (schema, routes, conventions, gems, controllers, config,
|
|
|
376
376
|
Every generated context file ships with **6 rules that force AI verification** before writing code. The protocol targets the exact cognitive failures that produce confident-wrong code: statistical priors overriding observed facts, pattern completion beating verification, stale context lies.
|
|
377
377
|
|
|
378
378
|
<details>
|
|
379
|
-
<summary><strong>The 6 rules (shown to AI in every CLAUDE.md / .cursor/rules / .github/instructions)</strong></summary>
|
|
379
|
+
<summary><strong>The 6 rules (shown to AI in every CLAUDE.md / .cursor/rules / .cursorrules / .github/instructions)</strong></summary>
|
|
380
380
|
|
|
381
381
|
<br>
|
|
382
382
|
|
|
@@ -403,7 +403,7 @@ graph TD
|
|
|
403
403
|
|
|
404
404
|
B --> C["MCP Server\nstdio / HTTP\n38 tools · 5 templates"]
|
|
405
405
|
B --> D["CLI Tools\nRake / Thor\nSame 38 tools"]
|
|
406
|
-
B --> E["Static Files\nCLAUDE.md · .cursor/rules
|
|
406
|
+
B --> E["Static Files\nCLAUDE.md · .cursor/rules/ · .cursorrules\n.github/instructions/"]
|
|
407
407
|
|
|
408
408
|
style A fill:#4a9eff,stroke:#2d7ad4,color:#fff
|
|
409
409
|
style B fill:#2d2d2d,stroke:#555,color:#fff
|
|
@@ -543,7 +543,7 @@ end
|
|
|
543
543
|
## About
|
|
544
544
|
|
|
545
545
|
Built by a Rails developer with 10+ years of production experience.<br>
|
|
546
|
-
|
|
546
|
+
2078 tests + 100-example e2e harness. 38 tools. 5 resource templates. 31 introspectors. Standalone or in-Gemfile.<br>
|
|
547
547
|
MIT licensed. [Contributions welcome.](CONTRIBUTING.md)
|
|
548
548
|
|
|
549
549
|
<br>
|
data/Rakefile
CHANGED
|
@@ -5,4 +5,42 @@ require "rspec/core/rake_task"
|
|
|
5
5
|
|
|
6
6
|
RSpec::Core::RakeTask.new(:spec)
|
|
7
7
|
|
|
8
|
+
# E2E harness — runs specs under spec/e2e/ with E2E=1 so they're not
|
|
9
|
+
# excluded by spec/spec_helper.rb. Each install-path spec spawns a
|
|
10
|
+
# fresh Rails app in a tmpdir and can take minutes.
|
|
11
|
+
#
|
|
12
|
+
# Usage:
|
|
13
|
+
# bundle exec rake e2e # full suite
|
|
14
|
+
# bundle exec rake e2e:in_gemfile # just Path A
|
|
15
|
+
# bundle exec rake e2e:standalone # just Path B
|
|
16
|
+
# bundle exec rake e2e:zero_config # just Path C
|
|
17
|
+
# bundle exec rake e2e:mcp # stdio + HTTP protocol specs
|
|
18
|
+
namespace :e2e do
|
|
19
|
+
RSpec::Core::RakeTask.new(:in_gemfile) do |t|
|
|
20
|
+
t.pattern = "spec/e2e/in_gemfile_install_spec.rb"
|
|
21
|
+
ENV["E2E"] = "1"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
RSpec::Core::RakeTask.new(:standalone) do |t|
|
|
25
|
+
t.pattern = "spec/e2e/standalone_install_spec.rb"
|
|
26
|
+
ENV["E2E"] = "1"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
RSpec::Core::RakeTask.new(:zero_config) do |t|
|
|
30
|
+
t.pattern = "spec/e2e/zero_config_install_spec.rb"
|
|
31
|
+
ENV["E2E"] = "1"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
RSpec::Core::RakeTask.new(:mcp) do |t|
|
|
35
|
+
t.pattern = "spec/e2e/mcp_{stdio,http}_protocol_spec.rb"
|
|
36
|
+
ENV["E2E"] = "1"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
desc "Run the full E2E harness (fresh Rails app per install path)"
|
|
41
|
+
RSpec::Core::RakeTask.new(:e2e) do |t|
|
|
42
|
+
t.pattern = "spec/e2e/**/*_spec.rb"
|
|
43
|
+
ENV["E2E"] = "1"
|
|
44
|
+
end
|
|
45
|
+
|
|
8
46
|
task default: :spec
|
data/demo/demo-trace.tape
CHANGED
|
@@ -9,11 +9,11 @@ Set Padding 12
|
|
|
9
9
|
Set Theme "Catppuccin Mocha"
|
|
10
10
|
Set TypingSpeed 30ms
|
|
11
11
|
|
|
12
|
-
Type "cd
|
|
12
|
+
Type "cd ~/my-rails-app"
|
|
13
13
|
Enter
|
|
14
14
|
Sleep 800ms
|
|
15
15
|
|
|
16
|
-
Type "rails 'ai:tool[search_code]' pattern=
|
|
16
|
+
Type "rails 'ai:tool[search_code]' pattern=publishable match_type=trace"
|
|
17
17
|
Sleep 400ms
|
|
18
18
|
Enter
|
|
19
19
|
Sleep 5s
|
data/demo/demo.tape
CHANGED
data/docs/ARCHITECTURE.md
CHANGED
|
@@ -173,7 +173,7 @@ Result: controller and view tools automatically include relevant schema informat
|
|
|
173
173
|
|:-----------|:-------|
|
|
174
174
|
| `ClaudeSerializer` | `CLAUDE.md` |
|
|
175
175
|
| `ClaudeRulesSerializer` | `.claude/rules/*.md` |
|
|
176
|
-
| `CursorRulesSerializer` | `.cursor/rules/*.mdc` |
|
|
176
|
+
| `CursorRulesSerializer` | `.cursor/rules/*.mdc` AND `.cursorrules` (legacy chat-agent fallback) |
|
|
177
177
|
| `CopilotSerializer` | `.github/copilot-instructions.md` |
|
|
178
178
|
| `CopilotInstructionsSerializer` | `.github/instructions/*.instructions.md` |
|
|
179
179
|
| `OpencodeSerializer` | `AGENTS.md` (root) |
|
data/docs/CLI.md
CHANGED
|
@@ -45,12 +45,12 @@ Run any of the 38 MCP tools from the terminal.
|
|
|
45
45
|
```bash
|
|
46
46
|
# Rake syntax
|
|
47
47
|
rails 'ai:tool[schema]' table=users detail=full
|
|
48
|
-
rails 'ai:tool[search_code]' pattern="
|
|
48
|
+
rails 'ai:tool[search_code]' pattern="publishable?" match_type=trace
|
|
49
49
|
rails 'ai:tool[model_details]' model=User
|
|
50
50
|
|
|
51
51
|
# Thor syntax
|
|
52
52
|
rails-ai-context tool schema --table users --detail full
|
|
53
|
-
rails-ai-context tool search_code --pattern "
|
|
53
|
+
rails-ai-context tool search_code --pattern "publishable?" --match-type trace
|
|
54
54
|
rails-ai-context tool model_details --model User
|
|
55
55
|
```
|
|
56
56
|
|
data/docs/FAQ.md
CHANGED
|
@@ -53,7 +53,7 @@ Yes, freely. Both generate identical context files and provide the same 38 tools
|
|
|
53
53
|
|
|
54
54
|
**Yes, commit these:**
|
|
55
55
|
- `.mcp.json`, `.cursor/mcp.json`, `.vscode/mcp.json`, `opencode.json`, `.codex/config.toml` — so teammates get MCP auto-discovery
|
|
56
|
-
- `CLAUDE.md`, `.cursor/rules/`, `.github/instructions/`, `AGENTS.md` — so AI has context
|
|
56
|
+
- `CLAUDE.md`, `.cursor/rules/`, `.cursorrules`, `.github/instructions/`, `AGENTS.md` — so AI has context
|
|
57
57
|
- `config/initializers/rails_ai_context.rb`, `.rails-ai-context.yml` — so config is shared
|
|
58
58
|
|
|
59
59
|
**Don't commit:**
|
|
@@ -126,7 +126,7 @@ Depends on your `ai_tools` config. For all tools:
|
|
|
126
126
|
| AI Tool | Files |
|
|
127
127
|
|:--------|:------|
|
|
128
128
|
| Claude | CLAUDE.md, .claude/rules/*.md |
|
|
129
|
-
| Cursor | .cursor/rules/*.mdc |
|
|
129
|
+
| Cursor | .cursor/rules/*.mdc AND .cursorrules (legacy fallback for chat agent) |
|
|
130
130
|
| Copilot | .github/copilot-instructions.md, .github/instructions/*.instructions.md |
|
|
131
131
|
| OpenCode | AGENTS.md, app/*/AGENTS.md |
|
|
132
132
|
| Codex | Shares AGENTS.md and OpenCode rules |
|
data/docs/GUIDE.md
CHANGED
|
@@ -460,7 +460,7 @@ Returns controller details: actions, filters, strong params, concerns. Automatic
|
|
|
460
460
|
|
|
461
461
|
| Param | Type | Description |
|
|
462
462
|
|-------|------|-------------|
|
|
463
|
-
| `controller` | string | Specific controller name (e.g. `UsersController`, `
|
|
463
|
+
| `controller` | string | Specific controller name (e.g. `UsersController`, `posts`, `admin/posts`). Case-insensitive, flexible format. |
|
|
464
464
|
| `action` | string | Specific action (e.g. `index`). Requires controller. Returns source code with applicable filters. |
|
|
465
465
|
| `detail` | string | `summary` / `standard` (default) / `full`. Ignored when controller is specified. |
|
|
466
466
|
| `limit` | integer | Max controllers to return when listing. Default: 50. |
|
|
@@ -502,7 +502,7 @@ Returns test infrastructure details. Optionally filter by model or controller to
|
|
|
502
502
|
| Param | Type | Description |
|
|
503
503
|
|-------|------|-------------|
|
|
504
504
|
| `model` | string | Show tests for a specific model (e.g. `User`). Also searches concern test paths (`spec/models/concerns/`, `test/models/concerns/`). |
|
|
505
|
-
| `controller` | string | Show tests for a specific controller (e.g. `
|
|
505
|
+
| `controller` | string | Show tests for a specific controller (e.g. `Posts`). |
|
|
506
506
|
| `detail` | string | `summary` / `standard` (default) / `full`. |
|
|
507
507
|
|
|
508
508
|
```
|
|
@@ -578,8 +578,8 @@ Returns view template contents, partials, and Stimulus controller references. In
|
|
|
578
578
|
|
|
579
579
|
| Param | Type | Description |
|
|
580
580
|
|-------|------|-------------|
|
|
581
|
-
| `controller` | string | Filter views by controller name (e.g. `
|
|
582
|
-
| `path` | string | Specific view path relative to `app/views` (e.g. `
|
|
581
|
+
| `controller` | string | Filter views by controller name (e.g. `posts`, `comments`). Use `layouts` for layout files. |
|
|
582
|
+
| `path` | string | Specific view path relative to `app/views` (e.g. `posts/index.html.erb`). Returns full content. |
|
|
583
583
|
| `detail` | string | `summary` / `standard` (default) / `full` |
|
|
584
584
|
|
|
585
585
|
**Examples:**
|
|
@@ -588,17 +588,17 @@ Returns view template contents, partials, and Stimulus controller references. In
|
|
|
588
588
|
rails_get_view()
|
|
589
589
|
→ Standard: all view files with partial/stimulus refs
|
|
590
590
|
|
|
591
|
-
rails_get_view(controller: "
|
|
592
|
-
→ All templates and partials for
|
|
591
|
+
rails_get_view(controller: "posts")
|
|
592
|
+
→ All templates and partials for PostsController
|
|
593
593
|
|
|
594
|
-
rails_get_view(path: "
|
|
594
|
+
rails_get_view(path: "posts/index.html.erb")
|
|
595
595
|
→ Full template content
|
|
596
596
|
|
|
597
597
|
rails_get_view(controller: "layouts")
|
|
598
598
|
→ Layout files
|
|
599
599
|
|
|
600
|
-
rails_get_view(controller: "
|
|
601
|
-
→ Full template content for all
|
|
600
|
+
rails_get_view(controller: "posts", detail: "full")
|
|
601
|
+
→ Full template content for all posts views
|
|
602
602
|
```
|
|
603
603
|
|
|
604
604
|
### rails_get_edit_context
|
|
@@ -609,17 +609,17 @@ Returns just enough context to make a surgical Edit to a file. Returns the targe
|
|
|
609
609
|
|
|
610
610
|
| Param | Type | Description |
|
|
611
611
|
|-------|------|-------------|
|
|
612
|
-
| `file` | string | **Required.** File path relative to Rails root (e.g. `app/models/
|
|
612
|
+
| `file` | string | **Required.** File path relative to Rails root (e.g. `app/models/post.rb`). |
|
|
613
613
|
| `near` | string | **Required.** What to find — a method name, keyword, or string to locate (e.g. `scope`, `def index`). |
|
|
614
614
|
| `context_lines` | integer | Lines of context above and below the match. Default: 5. |
|
|
615
615
|
|
|
616
616
|
**Examples:**
|
|
617
617
|
|
|
618
618
|
```
|
|
619
|
-
rails_get_edit_context(file: "app/models/
|
|
619
|
+
rails_get_edit_context(file: "app/models/post.rb", near: "scope")
|
|
620
620
|
→ Code around the first scope with line numbers, expanded to full method
|
|
621
621
|
|
|
622
|
-
rails_get_edit_context(file: "app/controllers/
|
|
622
|
+
rails_get_edit_context(file: "app/controllers/posts_controller.rb", near: "def index")
|
|
623
623
|
→ The index action source with surrounding context
|
|
624
624
|
```
|
|
625
625
|
|
|
@@ -631,22 +631,22 @@ Validates syntax of multiple files at once (Ruby, ERB, JavaScript). Optionally r
|
|
|
631
631
|
|
|
632
632
|
| Param | Type | Description |
|
|
633
633
|
|-------|------|-------------|
|
|
634
|
-
| `files` | array | **Required.** File paths relative to Rails root (e.g. `["app/models/
|
|
634
|
+
| `files` | array | **Required.** File paths relative to Rails root (e.g. `["app/models/post.rb", "app/views/posts/index.html.erb"]`). |
|
|
635
635
|
| `level` | string | `syntax` (default) — check syntax only (fast). `rails` — syntax + semantic checks (partial existence, route helpers, column references, strong params vs schema, callback methods, route-action consistency, has_many dependent, FK indexes, Stimulus controllers). |
|
|
636
636
|
|
|
637
637
|
**Examples:**
|
|
638
638
|
|
|
639
639
|
```
|
|
640
|
-
rails_validate(files: ["app/models/
|
|
641
|
-
→ ✓ app/models/
|
|
640
|
+
rails_validate(files: ["app/models/post.rb"])
|
|
641
|
+
→ ✓ app/models/post.rb — syntax OK
|
|
642
642
|
|
|
643
|
-
rails_validate(files: ["app/models/
|
|
643
|
+
rails_validate(files: ["app/models/post.rb", "app/controllers/posts_controller.rb", "app/views/posts/index.html.erb"])
|
|
644
644
|
→ Checks all three files, reports pass/fail for each
|
|
645
645
|
|
|
646
|
-
rails_validate(files: ["app/models/
|
|
646
|
+
rails_validate(files: ["app/models/post.rb"], level: "rails")
|
|
647
647
|
→ Syntax check + semantic warnings (e.g. validates :nonexistent_column, has_many without :dependent)
|
|
648
648
|
|
|
649
|
-
rails_validate(files: ["app/views/
|
|
649
|
+
rails_validate(files: ["app/views/posts/index.html.erb"], level: "rails")
|
|
650
650
|
→ Syntax check + partial existence, route helper validity, Stimulus controller existence
|
|
651
651
|
```
|
|
652
652
|
|
|
@@ -673,14 +673,14 @@ Smart result limiting: <10 results shows all, 10-100 shows half, >100 caps at 10
|
|
|
673
673
|
**Examples:**
|
|
674
674
|
|
|
675
675
|
```
|
|
676
|
-
rails_search_code(pattern: "
|
|
676
|
+
rails_search_code(pattern: "publishable?", match_type: "trace")
|
|
677
677
|
→ FULL PICTURE: definition with class context + source code + internal calls
|
|
678
678
|
+ sibling methods + app callers with route chain + test coverage (separated)
|
|
679
679
|
|
|
680
680
|
rails_search_code(pattern: "create", match_type: "definition")
|
|
681
681
|
→ Only `def create` / `def self.create` lines
|
|
682
682
|
|
|
683
|
-
rails_search_code(pattern: "
|
|
683
|
+
rails_search_code(pattern: "publishable", match_type: "call")
|
|
684
684
|
→ Only call sites (excludes the definition)
|
|
685
685
|
|
|
686
686
|
rails_search_code(pattern: "Controller", match_type: "class")
|
|
@@ -689,7 +689,7 @@ rails_search_code(pattern: "Controller", match_type: "class")
|
|
|
689
689
|
rails_search_code(pattern: "has_many", group_by_file: true)
|
|
690
690
|
→ Results grouped by file with match counts
|
|
691
691
|
|
|
692
|
-
rails_search_code(pattern: "
|
|
692
|
+
rails_search_code(pattern: "post", exclude_tests: true)
|
|
693
693
|
→ Skip test/spec directories
|
|
694
694
|
|
|
695
695
|
rails_search_code(pattern: "activate", match_type: "definition")
|
|
@@ -975,15 +975,15 @@ Get cross-layer context in a single call — combines schema, model, controller,
|
|
|
975
975
|
|
|
976
976
|
| Param | Type | Description |
|
|
977
977
|
|-------|------|-------------|
|
|
978
|
-
| `controller` | string | Controller name (e.g. `
|
|
978
|
+
| `controller` | string | Controller name (e.g. `PostsController`). Returns action source, filters, strong params, routes, views. |
|
|
979
979
|
| `action` | string | Specific action name (e.g. `create`). Requires controller. Returns full action context. |
|
|
980
|
-
| `model` | string | Model name (e.g. `
|
|
981
|
-
| `feature` | string | Feature keyword (e.g. `
|
|
980
|
+
| `model` | string | Model name (e.g. `Post`). Returns schema, associations, validations, scopes, callbacks, tests. |
|
|
981
|
+
| `feature` | string | Feature keyword (e.g. `post`). Like analyze_feature but includes schema columns and scope bodies. |
|
|
982
982
|
|
|
983
983
|
**Examples:**
|
|
984
984
|
|
|
985
985
|
```
|
|
986
|
-
rails_get_context(controller: "
|
|
986
|
+
rails_get_context(controller: "PostsController", action: "create")
|
|
987
987
|
→ Controller action source + model details + routes + views — everything for that action
|
|
988
988
|
|
|
989
989
|
rails_get_context(model: "User")
|
data/docs/QUICKSTART.md
CHANGED
|
@@ -55,7 +55,7 @@ The install generator created:
|
|
|
55
55
|
| File | Purpose |
|
|
56
56
|
|:-----|:--------|
|
|
57
57
|
| `.mcp.json` / `.cursor/mcp.json` / `.vscode/mcp.json` / `opencode.json` / `.codex/config.toml` | MCP auto-discovery — your AI tool detects these on project open |
|
|
58
|
-
| `CLAUDE.md` / `.cursor/rules/` / `.github/instructions/` | Static context rules your AI reads |
|
|
58
|
+
| `CLAUDE.md` / `.cursor/rules/` / `.cursorrules` / `.github/instructions/` / `AGENTS.md` | Static context rules your AI reads |
|
|
59
59
|
| `config/initializers/rails_ai_context.rb` | All configuration options |
|
|
60
60
|
| `.rails-ai-context.yml` | Config for standalone mode |
|
|
61
61
|
|