rails-ai-context 4.5.2 → 4.7.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 +41 -1
- data/CLAUDE.md +3 -3
- data/README.md +51 -24
- data/SECURITY.md +3 -0
- data/docs/GUIDE.md +7 -0
- data/exe/rails-ai-context +5 -1
- data/lib/generators/rails_ai_context/install/install_generator.rb +5 -1
- data/lib/rails_ai_context/configuration.rb +44 -30
- data/lib/rails_ai_context/introspector.rb +1 -1
- data/lib/rails_ai_context/introspectors/{convention_detector.rb → convention_introspector.rb} +1 -1
- data/lib/rails_ai_context/serializers/claude_rules_serializer.rb +13 -40
- data/lib/rails_ai_context/serializers/claude_serializer.rb +11 -191
- data/lib/rails_ai_context/serializers/compact_serializer_helper.rb +141 -0
- data/lib/rails_ai_context/serializers/copilot_instructions_serializer.rb +17 -75
- data/lib/rails_ai_context/serializers/copilot_serializer.rb +3 -3
- data/lib/rails_ai_context/serializers/cursor_rules_serializer.rb +19 -79
- data/lib/rails_ai_context/serializers/markdown_serializer.rb +14 -6
- data/lib/rails_ai_context/serializers/opencode_rules_serializer.rb +18 -60
- data/lib/rails_ai_context/serializers/opencode_serializer.rb +5 -141
- data/lib/rails_ai_context/serializers/stack_overview_helper.rb +121 -0
- data/lib/rails_ai_context/serializers/tool_guide_helper.rb +85 -100
- data/lib/rails_ai_context/tools/base_tool.rb +49 -24
- data/lib/rails_ai_context/tools/dependency_graph.rb +1 -2
- data/lib/rails_ai_context/tools/generate_test.rb +1 -2
- data/lib/rails_ai_context/tools/get_callbacks.rb +3 -35
- data/lib/rails_ai_context/tools/get_concern.rb +4 -31
- data/lib/rails_ai_context/tools/get_context.rb +1 -3
- data/lib/rails_ai_context/tools/get_model_details.rb +1 -2
- data/lib/rails_ai_context/tools/get_view.rb +2 -2
- data/lib/rails_ai_context/version.rb +1 -1
- data/lib/rails_ai_context.rb +0 -1
- data/server.json +3 -3
- metadata +11 -25
- data/lib/rails_ai_context/markdown_escape.rb +0 -15
- data/lib/rails_ai_context/serializers/rules_serializer.rb +0 -155
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c780366dc085c17be730aded4bbe8548b0e5e71c5c810caed96104a9379363fa
|
|
4
|
+
data.tar.gz: f5c46207b643df1a7dc1c5563c1d9e932f772ce5e27eb1839d9f14ddde116bd0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 934c4d703203801494a8addde164c71e56119e5701dd454574b0362d2a6d68523b6f0830654ff81eaa1d36fac7eca457374960e4e9fe54731f32431fe23ea8a4
|
|
7
|
+
data.tar.gz: ca2bf9e27db44fb35b8d9bd984748b7fce1108a013ef7ea6ec5a01757c48187b6ce6985c529ee8bf4df7cc9abd59085da8c356b3c73052e5196b07cc9a9a3790
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,30 @@ 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
|
+
## [4.7.0] — 2026-04-05
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Anti-Hallucination Protocol** — 6-rule verification section embedded in every generated context file (CLAUDE.md, AGENTS.md, .claude/rules/, .cursor/rules/, .github/instructions/, copilot-instructions.md). Targets specific AI failure modes: statistical priors overriding observed facts, pattern completion beating verification, inheritance blindness, empty-output-as-permission, stale-context-lies. Rules force AI to verify column/association/route/method/gem names before writing, mark assumptions with `[ASSUMPTION]` prefix, check inheritance chains, and re-query after writes. Enabled by default via new `config.anti_hallucination_rules` option (boolean, default: `true`). Set `false` to skip.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- **Repositioning: ground truth, not token savings** — the gem's mission is now explicit about what it actually does: stop AI from guessing your Rails app. Token savings are a side-effect, not the product. Updated README headline, "What stops being wrong" section (replaces "Measured token savings"), gemspec summary/description, server.json MCP registry description, docs/GUIDE.md intro, and the tools guide embedded in every generated CLAUDE.md/AGENTS.md/.cursor/rules. The core pitch: AI queries your running app for real schema, real associations, real filters — and writes correct code on the first try instead of iterating through corrections.
|
|
15
|
+
|
|
16
|
+
## [4.6.0] — 2026-04-04
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
- **Integration test suite** — 3 purpose-built Rails 8 apps exercising every gem feature end-to-end:
|
|
20
|
+
- `full_app` — comprehensive app (38 gems, 14 models, 15 controllers, 26 views, 5 jobs, 3 mailers, multi-database, ViewComponent, Stimulus, STI, polymorphic, AASM, PaperTrail, FriendlyId, encrypted attributes, CurrentAttributes, Flipper feature flags, Sentry monitoring, Pundit auth, Ransack search, Dry-rb, acts_as_tenant, Docker, Kamal, GitHub Actions CI, RSpec + FactoryBot)
|
|
21
|
+
- `api_app` — API-only app (Products/Orders/OrderItems, namespaced API v1 routes, CLI tool_mode)
|
|
22
|
+
- `minimal_app` — bare minimum app (single model, graceful degradation testing)
|
|
23
|
+
- **Master test runner** (`test_apps/run_all_tests.sh`) — validates Doctor, context generation, all 33 introspectors, all 39 MCP tools, Rake tasks, MCP server startup, and app-specific pattern detection across all 3 apps (222 tests)
|
|
24
|
+
- All 3 test apps achieve **100/100 AI Readiness Score**
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
- **Standalone CLI `full_gem_path` crash** — `Gem.loaded_specs.delete_if { |_, spec| !spec.default_gem? }` in the exe file cleared gem specs needed by MCP SDK at runtime (`json-schema` gem's `full_gem_path` returned nil). Added `!ENV["BUNDLE_BIN_PATH"]` guard so cleanup only runs in true standalone mode, not under `bundle exec`. This bug affected ALL `rails-ai-context tool` commands in standalone mode.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
- Test count: 1621 RSpec examples + 222 integration tests across 3 apps
|
|
31
|
+
|
|
8
32
|
## [4.5.2] — 2026-04-04
|
|
9
33
|
|
|
10
34
|
### Added
|
|
@@ -30,8 +54,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
30
54
|
- **CLI error messages** — Clean error messages for all CLI error paths
|
|
31
55
|
- **Rake/init parity** — `rake ai:context` and `init` command now match generator output
|
|
32
56
|
|
|
57
|
+
### Refactored
|
|
58
|
+
- **SLOP audit: ~640 lines removed** — comprehensive audit eliminating superfluous abstractions, dead code, and duplicated patterns
|
|
59
|
+
- **CompactSerializerHelper** — extracted shared logic from ClaudeSerializer and OpencodeSerializer, eliminating ~75% duplication
|
|
60
|
+
- **StackOverviewHelper consolidation** — moved `project_root`, `detect_service_files`, `detect_job_files`, `detect_before_actions`, `scope_names`, `notable_gems_list`, `arch_labels_hash`, `pattern_labels_hash`, `write_rule_files` into shared module, replacing 30+ duplicate copies across 6 serializers
|
|
61
|
+
- **Atomic file writes** — `write_rule_files` uses temp file + rename for crash-safe context file generation
|
|
62
|
+
- **ConventionDetector → ConventionIntrospector** — renamed for naming consistency with all 33 other introspectors
|
|
63
|
+
- **MarkdownEscape inlined** — single-use module inlined into MarkdownSerializer as private method
|
|
64
|
+
- **RulesSerializer deleted** — dead code never called by ContextFileSerializer
|
|
65
|
+
- **BaseTool cleanup** — removed dead `auto_compress`, `app_size`, `session_queried?` methods
|
|
66
|
+
- **IntrospectionError deleted** — exception class never raised anywhere
|
|
67
|
+
- **mobile_paths config removed** — config option never read by any introspector, tool, or serializer
|
|
68
|
+
- **server_version** — changed from attr_accessor to method delegating to `VERSION` constant
|
|
69
|
+
- **Configuration constants** — extracted `DEFAULT_EXCLUDED_FILTERS`, `DEFAULT_EXCLUDED_MIDDLEWARE`, `DEFAULT_EXCLUDED_CONCERNS` as frozen constants
|
|
70
|
+
- **Detail spec consolidation** — merged 5 detail spec files into their base spec counterparts
|
|
71
|
+
- **Orphaned spec cleanup** — removed `gem_introspector_spec.rb` duplicate (canonical spec already exists under introspectors/)
|
|
72
|
+
|
|
33
73
|
### Changed
|
|
34
|
-
- Test count:
|
|
74
|
+
- Test count: 1621 examples (consolidated from 1658 — no coverage lost, only duplicate/orphaned specs removed)
|
|
35
75
|
|
|
36
76
|
## [4.4.0] — 2026-04-03
|
|
37
77
|
|
data/CLAUDE.md
CHANGED
|
@@ -11,12 +11,11 @@ structure to AI assistants via the Model Context Protocol (MCP).
|
|
|
11
11
|
- `lib/rails_ai_context/introspectors/` — 33 introspectors (schema, models, routes, jobs, gems, conventions, stimulus, database_stats, controllers, views, view_templates, design_tokens, turbo, i18n, config, active_storage, action_text, auth, api, tests, rake_tasks, assets, devops, action_mailbox, migrations, seeds, middleware, engines, multi_database, components, accessibility, performance, frontend_frameworks)
|
|
12
12
|
- `lib/rails_ai_context/tools/` — 39 MCP tools using the official mcp SDK
|
|
13
13
|
- `lib/rails_ai_context/cli/` — CLI tool runner (`tool_runner.rb`) — executes MCP tools from rake/Thor
|
|
14
|
-
- `lib/rails_ai_context/serializers/` — Output formatters (claude, claude_rules, opencode, opencode_rules, cursor_rules, copilot, copilot_instructions,
|
|
14
|
+
- `lib/rails_ai_context/serializers/` — Output formatters (claude, claude_rules, opencode, opencode_rules, cursor_rules, copilot, copilot_instructions, markdown, JSON, context_file_serializer, compact_serializer_helper, test_command_detection, tool_guide_helper, design_system_helper, stack_overview_helper)
|
|
15
15
|
- `lib/rails_ai_context/resources.rb` — MCP resources (static data AI clients read directly)
|
|
16
16
|
- `lib/rails_ai_context/server.rb` — MCP server configuration (stdio + HTTP transports)
|
|
17
17
|
- `lib/rails_ai_context/middleware.rb` — Rack middleware for auto-mounting MCP HTTP endpoint
|
|
18
18
|
- `lib/rails_ai_context/safe_file.rb` — Safe file reading with size limits and error handling
|
|
19
|
-
- `lib/rails_ai_context/markdown_escape.rb` — Escapes markdown special characters in dynamic content
|
|
20
19
|
- `lib/rails_ai_context/fingerprinter.rb` — SHA256 file fingerprinting for cache invalidation
|
|
21
20
|
- `lib/rails_ai_context/doctor.rb` — Diagnostic checks and AI readiness scoring
|
|
22
21
|
- `lib/rails_ai_context/live_reload.rb` — MCP live reload: watches files, invalidates caches, notifies AI clients
|
|
@@ -64,11 +63,12 @@ structure to AI assistants via the Model Context Protocol (MCP).
|
|
|
64
63
|
35. **YAML config** — `.rails-ai-context.yml` as alternative to initializer. Supports all config options except `custom_tools` (Ruby classes) and `excluded_concerns` (regex). Precedence: initializer > YAML > defaults.
|
|
65
64
|
36. **Config auto-loading** — `Configuration.auto_load!` checks `configured_via_block?` flag. If initializer ran, YAML is skipped. Corrupted YAML degrades gracefully with a warning.
|
|
66
65
|
37. **Three install paths** — In-Gemfile (`rails generate rails_ai_context:install`), Standalone (`rails-ai-context init`), Zero config (just run `rails-ai-context serve` with defaults). Users can switch between paths freely; `.mcp.json` command is updated on re-init/re-install.
|
|
66
|
+
38. **Anti-Hallucination Protocol** — 6-rule verification section embedded in every generated context file (CLAUDE.md, AGENTS.md, .claude/rules/, .cursor/rules/, .github/instructions/). Targets AI failure modes: statistical priors overriding facts, pattern completion beating verification, stale context. Toggleable via `config.anti_hallucination_rules` (default: true). Rendered by `tools_anti_hallucination_section` in `tool_guide_helper.rb`, placed between intro and detail_guidance in both full and compact render methods.
|
|
67
67
|
|
|
68
68
|
## Testing
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
|
-
bundle exec rspec # Run specs (
|
|
71
|
+
bundle exec rspec # Run specs (1627 examples)
|
|
72
72
|
bundle exec rubocop # Lint
|
|
73
73
|
```
|
|
74
74
|
|
data/README.md
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
[](https://registry.modelcontextprotocol.io)
|
|
20
20
|
[](https://github.com/crisnahine/rails-ai-context)
|
|
21
21
|
[](https://github.com/crisnahine/rails-ai-context)
|
|
22
|
-
[](https://github.com/crisnahine/rails-ai-context/actions)
|
|
23
23
|
[](LICENSE)
|
|
24
24
|
|
|
25
25
|
</div>
|
|
@@ -35,12 +35,12 @@ You've seen it. Your AI:
|
|
|
35
35
|
- **Uses the wrong association name** — `user.posts` when it's `user.articles`
|
|
36
36
|
- **Generates tests that don't match your patterns** — factories when you use fixtures, or the reverse
|
|
37
37
|
- **Adds a gem you already have** — or calls an API from one you don't
|
|
38
|
-
- **Reads 2,000 lines of schema.rb** to answer a question about one table
|
|
39
38
|
- **Misses `before_action` filters from parent controllers** — then wonders why auth fails
|
|
39
|
+
- **Invents a method** that isn't in your codebase — then you spend 10 minutes finding out
|
|
40
40
|
|
|
41
41
|
You catch it. You fix it. You re-prompt. It breaks something else.
|
|
42
42
|
|
|
43
|
-
**
|
|
43
|
+
**The real cost of AI coding isn't the tokens — it's the correction loop.** Every guess is a round-trip: you catch it, you fix it, you re-prompt, and something adjacent breaks. This gem kills the guessing at its source.
|
|
44
44
|
|
|
45
45
|
<br>
|
|
46
46
|
|
|
@@ -82,37 +82,41 @@ One call returns: definition + source code + every caller grouped by type + test
|
|
|
82
82
|
|
|
83
83
|
<br>
|
|
84
84
|
|
|
85
|
-
##
|
|
85
|
+
## What stops being wrong
|
|
86
86
|
|
|
87
|
-
Real
|
|
87
|
+
Real scenarios where AI goes sideways — and what it does instead with ground truth:
|
|
88
88
|
|
|
89
|
-
|
|
|
90
|
-
|
|
91
|
-
|
|
|
92
|
-
|
|
|
93
|
-
|
|
|
94
|
-
|
|
|
95
|
-
|
|
|
89
|
+
| You ask AI to... | Without — AI guesses | With — AI verifies first |
|
|
90
|
+
|:-----|:-----|:-----|
|
|
91
|
+
| Add a `subscription_tier` column to users | Writes the migration, duplicates an existing column | Reads live schema, spots `subscription_status` already exists, asks before migrating |
|
|
92
|
+
| Call `user.posts` in a controller | Uses the guess; runtime `NoMethodError` | Resolves the actual association (`user.articles`) from the model |
|
|
93
|
+
| Write tests for a new model | Scaffolds with FactoryBot | Detects your fixture-based suite and matches it |
|
|
94
|
+
| Fix a failing create action | Misses inherited `before_action :authenticate_user!` | Returns parent-controller filters inline with the action source |
|
|
95
|
+
| Build a dashboard page | Invents Tailwind classes from memory | Returns your actual button/card/alert patterns, copy-paste ready |
|
|
96
|
+
| Trace where `can_cook?` is used | Reads 6 files sequentially, still misses callers | Single call: definition + source + every caller + tests |
|
|
96
97
|
|
|
97
98
|
<details>
|
|
98
|
-
<summary><strong>
|
|
99
|
+
<summary><strong>Verify it on your own app</strong></summary>
|
|
99
100
|
|
|
100
101
|
<br>
|
|
101
102
|
|
|
103
|
+
Run these before and after installing to see what changes in *your* codebase:
|
|
104
|
+
|
|
102
105
|
```bash
|
|
103
|
-
# Schema:
|
|
104
|
-
|
|
105
|
-
rails 'ai:tool[schema]' table=users | wc -c
|
|
106
|
+
# Schema: does AI know what columns exist?
|
|
107
|
+
rails 'ai:tool[schema]' table=users
|
|
106
108
|
|
|
107
|
-
# Trace:
|
|
108
|
-
rails 'ai:tool[search_code]' pattern=your_method match_type=trace
|
|
109
|
+
# Trace: find every caller of a method across the codebase
|
|
110
|
+
rails 'ai:tool[search_code]' pattern=your_method match_type=trace
|
|
111
|
+
|
|
112
|
+
# Model: associations, scopes, callbacks, concerns — all resolved
|
|
113
|
+
rails 'ai:tool[model_details]' model=User
|
|
109
114
|
|
|
110
|
-
#
|
|
111
|
-
|
|
112
|
-
rails 'ai:tool[model_details]' model=User | wc -c
|
|
115
|
+
# Controllers: action source + inherited filters + strong params in one shot
|
|
116
|
+
rails 'ai:tool[controllers]' controller=UsersController action=create
|
|
113
117
|
```
|
|
114
118
|
|
|
115
|
-
|
|
119
|
+
Compare what AI outputs with and without these tools wired in. The difference is measured in *corrections avoided*, not bytes saved.
|
|
116
120
|
|
|
117
121
|
</details>
|
|
118
122
|
|
|
@@ -230,7 +234,7 @@ rails 'ai:tool[stimulus]' controller=chart
|
|
|
230
234
|
|
|
231
235
|
## 39 Tools
|
|
232
236
|
|
|
233
|
-
Every tool is **read-only** and returns
|
|
237
|
+
Every tool is **read-only** and returns data verified against your actual app — not guesses, not training data.
|
|
234
238
|
|
|
235
239
|
<details>
|
|
236
240
|
<summary><strong>Search & Trace</strong></summary>
|
|
@@ -339,6 +343,28 @@ Every tool is **read-only** and returns structured, token-efficient context.
|
|
|
339
343
|
|
|
340
344
|
<br>
|
|
341
345
|
|
|
346
|
+
## Anti-Hallucination Protocol
|
|
347
|
+
|
|
348
|
+
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.
|
|
349
|
+
|
|
350
|
+
<details>
|
|
351
|
+
<summary><strong>The 6 rules (shown to AI in every CLAUDE.md / .cursor/rules / .github/instructions)</strong></summary>
|
|
352
|
+
|
|
353
|
+
<br>
|
|
354
|
+
|
|
355
|
+
1. **Verify before you write.** Never reference a column, association, route, helper, method, class, partial, or gem not verified in THIS project via a tool call in THIS turn. Never invent names that "sound right."
|
|
356
|
+
2. **Mark every assumption.** If proceeding without verification, prefix with `[ASSUMPTION]`. Silent assumptions forbidden. "I'd need to check X first" is a preferred answer.
|
|
357
|
+
3. **Training data describes average Rails. This app isn't average.** When something feels "obviously" standard Rails, query anyway. Check `rails_get_conventions` + `rails_get_gems` BEFORE scaffolding.
|
|
358
|
+
4. **Check the inheritance chain before every edit.** Inherited `before_action` filters, concerns, includes, STI parents. Inheritance is never flat.
|
|
359
|
+
5. **Empty tool output is information, not permission.** "0 callers found" signals investigation, not license to proceed on guesses.
|
|
360
|
+
6. **Stale context lies. Re-query after writes.** Earlier tool output may be wrong after edits.
|
|
361
|
+
|
|
362
|
+
Enabled by default. Disable with `config.anti_hallucination_rules = false` if you prefer your own rules.
|
|
363
|
+
|
|
364
|
+
</details>
|
|
365
|
+
|
|
366
|
+
<br>
|
|
367
|
+
|
|
342
368
|
## How it works
|
|
343
369
|
|
|
344
370
|
```
|
|
@@ -419,6 +445,7 @@ end
|
|
|
419
445
|
| `preset` | `:full` | `:full` (33 introspectors) or `:standard` (19) |
|
|
420
446
|
| `context_mode` | `:compact` | `:compact` (150 lines) or `:full` |
|
|
421
447
|
| `generate_root_files` | `true` | Set `false` for split rules only |
|
|
448
|
+
| `anti_hallucination_rules` | `true` | Embed 6-rule verification protocol in generated context files |
|
|
422
449
|
| `cache_ttl` | `60` | Cache TTL in seconds |
|
|
423
450
|
| `max_tool_response_chars` | `200_000` | Safety cap for tool responses |
|
|
424
451
|
| `live_reload` | `:auto` | `:auto`, `true`, or `false` |
|
|
@@ -444,7 +471,7 @@ end
|
|
|
444
471
|
## About
|
|
445
472
|
|
|
446
473
|
Built by a Rails developer with 10+ years of production experience.<br>
|
|
447
|
-
|
|
474
|
+
1621 tests. 39 tools. 33 introspectors. Standalone or in-Gemfile.<br>
|
|
448
475
|
MIT licensed. [Contributions welcome.](CONTRIBUTING.md)
|
|
449
476
|
|
|
450
477
|
<br>
|
data/SECURITY.md
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
| Version | Supported |
|
|
6
6
|
|---------|--------------------|
|
|
7
|
+
| 4.6.x | :white_check_mark: |
|
|
8
|
+
| 4.5.x | :white_check_mark: |
|
|
9
|
+
| 4.4.x | :white_check_mark: |
|
|
7
10
|
| 4.3.x | :white_check_mark: |
|
|
8
11
|
| 4.2.x | :white_check_mark: (4.2.1 includes security hardening) |
|
|
9
12
|
| 4.1.x | :white_check_mark: |
|
data/docs/GUIDE.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
> Full documentation for [rails-ai-context](https://github.com/crisnahine/rails-ai-context).
|
|
4
4
|
> For a quick overview, see the [README](../README.md).
|
|
5
|
+
>
|
|
6
|
+
> **Why this gem exists:** AI coding assistants guess your Rails app. They invent columns,
|
|
7
|
+
> use wrong association names, miss inherited filters, and scaffold tests that don't match
|
|
8
|
+
> your patterns. This gem turns your running app into the source of truth — so agents query
|
|
9
|
+
> real schema, real associations, and real conventions on demand, and write correct code
|
|
10
|
+
> on the first try.
|
|
5
11
|
|
|
6
12
|
---
|
|
7
13
|
|
|
@@ -1290,6 +1296,7 @@ end
|
|
|
1290
1296
|
| `server_name` | String | `"rails-ai-context"` | MCP server name |
|
|
1291
1297
|
| `server_version` | String | gem version | MCP server version |
|
|
1292
1298
|
| `generate_root_files` | Boolean | `true` | Generate root files (CLAUDE.md, etc.) — set `false` for split rules only |
|
|
1299
|
+
| `anti_hallucination_rules` | Boolean | `true` | Embed 6-rule Anti-Hallucination Protocol in generated context files — set `false` to skip |
|
|
1293
1300
|
| `max_file_size` | Integer | `5_000_000` | Per-file read limit for tools (5MB) |
|
|
1294
1301
|
| `max_test_file_size` | Integer | `1_000_000` | Test file read limit (1MB) |
|
|
1295
1302
|
| `max_schema_file_size` | Integer | `10_000_000` | schema.rb / structure.sql parse limit (10MB) |
|
data/exe/rails-ai-context
CHANGED
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
# may need different versions of those deps (e.g., bigdecimal 4.1.0 activated here
|
|
7
7
|
# but Gemfile.lock wants 4.0.1). Clear non-default gem activations so Bundler can
|
|
8
8
|
# resolve cleanly. The $LOAD_PATH entries remain (Bundler.setup replaces them anyway).
|
|
9
|
-
|
|
9
|
+
#
|
|
10
|
+
# Skip this when running under `bundle exec` — Bundler has already resolved gems
|
|
11
|
+
# correctly, and clearing specs breaks gems that look up their own path at runtime
|
|
12
|
+
# (e.g., MCP SDK reads Gem.loaded_specs["json-schema"].full_gem_path).
|
|
13
|
+
if defined?(Gem) && Gem.respond_to?(:loaded_specs) && !ENV["BUNDLE_BIN_PATH"]
|
|
10
14
|
Gem.loaded_specs.delete_if { |_, spec| !spec.default_gem? }
|
|
11
15
|
end
|
|
12
16
|
|
|
@@ -187,6 +187,11 @@ module RailsAiContext
|
|
|
187
187
|
# Whether to generate root files (CLAUDE.md, AGENTS.md, etc.)
|
|
188
188
|
# Set false to only generate split rules (.claude/rules/, .cursor/rules/, etc.)
|
|
189
189
|
# config.generate_root_files = true
|
|
190
|
+
|
|
191
|
+
# Anti-Hallucination Protocol: 6-rule verification section embedded in every
|
|
192
|
+
# generated context file. Forces AI to verify facts before writing code.
|
|
193
|
+
# Default: true. Set false to skip the protocol entirely.
|
|
194
|
+
# config.anti_hallucination_rules = true
|
|
190
195
|
SECTION
|
|
191
196
|
"Models & Filtering" => <<~SECTION,
|
|
192
197
|
# ── Models & Filtering ────────────────────────────────────────────
|
|
@@ -257,7 +262,6 @@ module RailsAiContext
|
|
|
257
262
|
# ── Frontend Framework Detection ─────────────────────────────────
|
|
258
263
|
# Auto-detected from package.json, config/vite.json, etc. Override only if needed.
|
|
259
264
|
# config.frontend_paths = ["app/frontend", "../web-client"]
|
|
260
|
-
# config.mobile_paths = ["../mobile-app"]
|
|
261
265
|
SECTION
|
|
262
266
|
}.freeze
|
|
263
267
|
|
|
@@ -13,11 +13,12 @@ module RailsAiContext
|
|
|
13
13
|
# All YAML-supported keys (explicit allowlist for safety)
|
|
14
14
|
YAML_KEYS = %i[
|
|
15
15
|
ai_tools tool_mode preset context_mode generate_root_files claude_max_lines
|
|
16
|
-
|
|
16
|
+
anti_hallucination_rules
|
|
17
|
+
server_name cache_ttl max_tool_response_chars
|
|
17
18
|
live_reload live_reload_debounce auto_mount http_path http_bind http_port
|
|
18
19
|
output_dir skip_tools excluded_models excluded_controllers
|
|
19
20
|
excluded_route_prefixes excluded_filters excluded_middleware excluded_paths
|
|
20
|
-
sensitive_patterns search_extensions concern_paths frontend_paths
|
|
21
|
+
sensitive_patterns search_extensions concern_paths frontend_paths
|
|
21
22
|
max_file_size max_test_file_size max_schema_file_size max_view_total_size
|
|
22
23
|
max_view_file_size max_search_results max_validate_files
|
|
23
24
|
query_timeout query_row_limit query_redacted_columns allow_query_in_production
|
|
@@ -79,7 +80,11 @@ module RailsAiContext
|
|
|
79
80
|
}.freeze
|
|
80
81
|
|
|
81
82
|
# MCP server settings
|
|
82
|
-
attr_accessor :server_name
|
|
83
|
+
attr_accessor :server_name
|
|
84
|
+
|
|
85
|
+
def server_version
|
|
86
|
+
RailsAiContext::VERSION
|
|
87
|
+
end
|
|
83
88
|
|
|
84
89
|
# Which introspectors to run
|
|
85
90
|
attr_accessor :introspectors
|
|
@@ -129,6 +134,11 @@ module RailsAiContext
|
|
|
129
134
|
# When false, only generates split rule files (.claude/rules/, .cursor/rules/, etc.)
|
|
130
135
|
attr_accessor :generate_root_files
|
|
131
136
|
|
|
137
|
+
# Whether to embed the Anti-Hallucination Protocol section in generated context files.
|
|
138
|
+
# Default: true. Set false to skip the 6-rule verification protocol in CLAUDE.md,
|
|
139
|
+
# AGENTS.md, .claude/rules/, .cursor/rules/, .github/instructions/.
|
|
140
|
+
attr_accessor :anti_hallucination_rules
|
|
141
|
+
|
|
132
142
|
# File size limits (bytes) — increase for larger projects
|
|
133
143
|
attr_accessor :max_file_size # Per-file read limit for tools (default: 2MB)
|
|
134
144
|
attr_accessor :max_test_file_size # Test file read limit (default: 500KB)
|
|
@@ -151,6 +161,33 @@ module RailsAiContext
|
|
|
151
161
|
# Tool invocation mode: :mcp (MCP primary + CLI fallback) or :cli (CLI only)
|
|
152
162
|
attr_accessor :tool_mode
|
|
153
163
|
|
|
164
|
+
DEFAULT_EXCLUDED_FILTERS = %w[
|
|
165
|
+
verify_authenticity_token verify_same_origin_request
|
|
166
|
+
turbo_tracking_request_id handle_unverified_request
|
|
167
|
+
mark_for_same_origin_verification
|
|
168
|
+
].freeze
|
|
169
|
+
|
|
170
|
+
DEFAULT_EXCLUDED_MIDDLEWARE = %w[
|
|
171
|
+
Rack::Sendfile ActionDispatch::Static ActionDispatch::Executor
|
|
172
|
+
ActionDispatch::ServerTiming Rack::Runtime
|
|
173
|
+
ActionDispatch::RequestId ActionDispatch::RemoteIp
|
|
174
|
+
Rails::Rack::Logger ActionDispatch::ShowExceptions
|
|
175
|
+
ActionDispatch::DebugExceptions ActionDispatch::Callbacks
|
|
176
|
+
ActionDispatch::Cookies ActionDispatch::Session::CookieStore
|
|
177
|
+
ActionDispatch::Flash ActionDispatch::ContentSecurityPolicy::Middleware
|
|
178
|
+
ActionDispatch::PermissionsPolicy::Middleware ActionDispatch::ActionableExceptions
|
|
179
|
+
Rack::Head Rack::ConditionalGet Rack::ETag Rack::TempfileReaper
|
|
180
|
+
ActiveRecord::Migration::CheckPending ActionDispatch::HostAuthorization
|
|
181
|
+
Rack::MethodOverride ActionDispatch::Session::AbstractSecureStore
|
|
182
|
+
].freeze
|
|
183
|
+
|
|
184
|
+
DEFAULT_EXCLUDED_CONCERNS = [
|
|
185
|
+
/::Generated/,
|
|
186
|
+
/\A(ActiveRecord|ActiveModel|ActiveSupport|ActionText|ActionMailbox|ActiveStorage)/,
|
|
187
|
+
/\A(ActionDispatch|ActionController|ActionView|AbstractController)/,
|
|
188
|
+
/\A(Devise::Models|Devise::Orm|Bullet::|Turbo::|GlobalID::|Rolify::)/
|
|
189
|
+
].freeze
|
|
190
|
+
|
|
154
191
|
# Filtering — customize what's hidden from AI output
|
|
155
192
|
attr_accessor :excluded_controllers # Controller classes hidden from listings (e.g. DeviseController)
|
|
156
193
|
attr_accessor :excluded_route_prefixes # Route controller prefixes hidden with app_only (e.g. action_mailbox/)
|
|
@@ -164,7 +201,6 @@ module RailsAiContext
|
|
|
164
201
|
|
|
165
202
|
# Frontend framework detection (optional overrides — auto-detected if nil)
|
|
166
203
|
attr_accessor :frontend_paths # User-declared frontend dirs (e.g. ["app/frontend", "../web-client"])
|
|
167
|
-
attr_accessor :mobile_paths # User-declared mobile dirs (e.g. ["../mobile-app"])
|
|
168
204
|
|
|
169
205
|
# Database query tool settings (rails_query)
|
|
170
206
|
attr_accessor :query_timeout # Statement timeout in seconds (default: 5)
|
|
@@ -177,7 +213,6 @@ module RailsAiContext
|
|
|
177
213
|
|
|
178
214
|
def initialize
|
|
179
215
|
@server_name = "rails-ai-context"
|
|
180
|
-
@server_version = RailsAiContext::VERSION
|
|
181
216
|
@introspectors = PRESETS[:full].dup
|
|
182
217
|
@excluded_paths = %w[node_modules tmp log vendor .git doc docs]
|
|
183
218
|
@sensitive_patterns = %w[
|
|
@@ -202,6 +237,7 @@ module RailsAiContext
|
|
|
202
237
|
@live_reload = :auto
|
|
203
238
|
@live_reload_debounce = 1.5
|
|
204
239
|
@generate_root_files = true
|
|
240
|
+
@anti_hallucination_rules = true
|
|
205
241
|
@max_file_size = 5_000_000
|
|
206
242
|
@max_test_file_size = 1_000_000
|
|
207
243
|
@max_schema_file_size = 10_000_000
|
|
@@ -211,30 +247,9 @@ module RailsAiContext
|
|
|
211
247
|
@max_validate_files = 50
|
|
212
248
|
@excluded_controllers = %w[DeviseController Devise::OmniauthCallbacksController]
|
|
213
249
|
@excluded_route_prefixes = %w[action_mailbox/ active_storage/ rails/ conductor/ devise/ turbo/]
|
|
214
|
-
@excluded_concerns =
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
/\A(ActionDispatch|ActionController|ActionView|AbstractController)/,
|
|
218
|
-
/\A(Devise::Models|Devise::Orm|Bullet::|Turbo::|GlobalID::|Rolify::)/
|
|
219
|
-
]
|
|
220
|
-
@excluded_filters = %w[
|
|
221
|
-
verify_authenticity_token verify_same_origin_request
|
|
222
|
-
turbo_tracking_request_id handle_unverified_request
|
|
223
|
-
mark_for_same_origin_verification
|
|
224
|
-
]
|
|
225
|
-
@excluded_middleware = %w[
|
|
226
|
-
Rack::Sendfile ActionDispatch::Static ActionDispatch::Executor
|
|
227
|
-
ActionDispatch::ServerTiming Rack::Runtime
|
|
228
|
-
ActionDispatch::RequestId ActionDispatch::RemoteIp
|
|
229
|
-
Rails::Rack::Logger ActionDispatch::ShowExceptions
|
|
230
|
-
ActionDispatch::DebugExceptions ActionDispatch::Callbacks
|
|
231
|
-
ActionDispatch::Cookies ActionDispatch::Session::CookieStore
|
|
232
|
-
ActionDispatch::Flash ActionDispatch::ContentSecurityPolicy::Middleware
|
|
233
|
-
ActionDispatch::PermissionsPolicy::Middleware ActionDispatch::ActionableExceptions
|
|
234
|
-
Rack::Head Rack::ConditionalGet Rack::ETag Rack::TempfileReaper
|
|
235
|
-
ActiveRecord::Migration::CheckPending ActionDispatch::HostAuthorization
|
|
236
|
-
Rack::MethodOverride ActionDispatch::Session::AbstractSecureStore
|
|
237
|
-
]
|
|
250
|
+
@excluded_concerns = DEFAULT_EXCLUDED_CONCERNS.dup
|
|
251
|
+
@excluded_filters = DEFAULT_EXCLUDED_FILTERS.dup
|
|
252
|
+
@excluded_middleware = DEFAULT_EXCLUDED_MIDDLEWARE.dup
|
|
238
253
|
@custom_tools = []
|
|
239
254
|
@skip_tools = []
|
|
240
255
|
@ai_tools = nil
|
|
@@ -242,7 +257,6 @@ module RailsAiContext
|
|
|
242
257
|
@search_extensions = %w[rb js erb yml yaml json ts tsx vue svelte haml slim]
|
|
243
258
|
@concern_paths = %w[app/models/concerns app/controllers/concerns]
|
|
244
259
|
@frontend_paths = nil
|
|
245
|
-
@mobile_paths = nil
|
|
246
260
|
@query_timeout = 5
|
|
247
261
|
@query_row_limit = 100
|
|
248
262
|
@query_redacted_columns = %w[
|
|
@@ -63,7 +63,7 @@ module RailsAiContext
|
|
|
63
63
|
when :routes then Introspectors::RouteIntrospector.new(app)
|
|
64
64
|
when :jobs then Introspectors::JobIntrospector.new(app)
|
|
65
65
|
when :gems then Introspectors::GemIntrospector.new(app)
|
|
66
|
-
when :conventions then Introspectors::
|
|
66
|
+
when :conventions then Introspectors::ConventionIntrospector.new(app)
|
|
67
67
|
when :stimulus then Introspectors::StimulusIntrospector.new(app)
|
|
68
68
|
when :database_stats then Introspectors::DatabaseStatsIntrospector.new(app)
|
|
69
69
|
when :controllers then Introspectors::ControllerIntrospector.new(app)
|
data/lib/rails_ai_context/introspectors/{convention_detector.rb → convention_introspector.rb}
RENAMED
|
@@ -4,7 +4,7 @@ module RailsAiContext
|
|
|
4
4
|
module Introspectors
|
|
5
5
|
# Detects high-level Rails conventions and patterns in use,
|
|
6
6
|
# giving AI assistants critical context about the app's architecture.
|
|
7
|
-
class
|
|
7
|
+
class ConventionIntrospector
|
|
8
8
|
attr_reader :app
|
|
9
9
|
|
|
10
10
|
def initialize(app)
|
|
@@ -19,34 +19,18 @@ module RailsAiContext
|
|
|
19
19
|
# @return [Hash] { written: [paths], skipped: [paths] }
|
|
20
20
|
def call(output_dir)
|
|
21
21
|
rules_dir = File.join(output_dir, ".claude", "rules")
|
|
22
|
-
FileUtils.mkdir_p(rules_dir)
|
|
23
|
-
|
|
24
|
-
written = []
|
|
25
|
-
skipped = []
|
|
26
22
|
|
|
27
23
|
files = {
|
|
28
|
-
"rails-context.md" => render_context_overview,
|
|
29
|
-
"rails-schema.md" => render_schema_reference,
|
|
30
|
-
"rails-models.md" => render_models_reference,
|
|
31
|
-
"rails-ui-patterns.md" => render_ui_patterns_reference,
|
|
32
|
-
"rails-mcp-tools.md" => render_mcp_tools_reference,
|
|
33
|
-
"rails-components.md" => render_components_reference,
|
|
34
|
-
"rails-accessibility.md" => render_accessibility_reference
|
|
24
|
+
File.join(rules_dir, "rails-context.md") => render_context_overview,
|
|
25
|
+
File.join(rules_dir, "rails-schema.md") => render_schema_reference,
|
|
26
|
+
File.join(rules_dir, "rails-models.md") => render_models_reference,
|
|
27
|
+
File.join(rules_dir, "rails-ui-patterns.md") => render_ui_patterns_reference,
|
|
28
|
+
File.join(rules_dir, "rails-mcp-tools.md") => render_mcp_tools_reference,
|
|
29
|
+
File.join(rules_dir, "rails-components.md") => render_components_reference,
|
|
30
|
+
File.join(rules_dir, "rails-accessibility.md") => render_accessibility_reference
|
|
35
31
|
}
|
|
36
32
|
|
|
37
|
-
files
|
|
38
|
-
next unless content
|
|
39
|
-
|
|
40
|
-
filepath = File.join(rules_dir, filename)
|
|
41
|
-
if File.exist?(filepath) && File.read(filepath) == content
|
|
42
|
-
skipped << filepath
|
|
43
|
-
else
|
|
44
|
-
File.write(filepath, content)
|
|
45
|
-
written << filepath
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
{ written: written, skipped: skipped }
|
|
33
|
+
write_rule_files(files)
|
|
50
34
|
end
|
|
51
35
|
|
|
52
36
|
private
|
|
@@ -74,17 +58,8 @@ module RailsAiContext
|
|
|
74
58
|
lines.concat(full_preset_stack_lines)
|
|
75
59
|
|
|
76
60
|
# ApplicationController before_actions — apply to all controllers
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
app_ctrl_file = File.join(root, "app", "controllers", "application_controller.rb")
|
|
80
|
-
if File.exist?(app_ctrl_file)
|
|
81
|
-
source = File.read(app_ctrl_file)
|
|
82
|
-
before_actions = source.scan(/before_action\s+:([\w!?]+)/).flatten
|
|
83
|
-
if before_actions.any?
|
|
84
|
-
lines << "" << "**Global before_actions:** #{before_actions.join(', ')}"
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
rescue => e; $stderr.puts "[rails-ai-context] Serializer section skipped: #{e.message}"; end
|
|
61
|
+
before_actions = detect_before_actions
|
|
62
|
+
lines << "" << "**Global before_actions:** #{before_actions.join(', ')}" if before_actions.any?
|
|
88
63
|
|
|
89
64
|
lines << ""
|
|
90
65
|
lines << "ALWAYS use MCP tools for context — do NOT read reference files directly."
|
|
@@ -206,7 +181,7 @@ module RailsAiContext
|
|
|
206
181
|
|
|
207
182
|
# Include scopes so agents know available query methods
|
|
208
183
|
scopes = data[:scopes] || []
|
|
209
|
-
scope_names = scopes
|
|
184
|
+
scope_names = scope_names(scopes)
|
|
210
185
|
lines << " scopes: #{scope_names.join(', ')}" if scopes.any?
|
|
211
186
|
|
|
212
187
|
# Instance methods — filter Devise/framework internals that add noise
|
|
@@ -248,8 +223,7 @@ module RailsAiContext
|
|
|
248
223
|
|
|
249
224
|
# Shared partials — so agents reuse them instead of recreating
|
|
250
225
|
begin
|
|
251
|
-
|
|
252
|
-
shared_dir = File.join(root, "app", "views", "shared")
|
|
226
|
+
shared_dir = File.join(project_root, "app", "views", "shared")
|
|
253
227
|
if Dir.exist?(shared_dir)
|
|
254
228
|
partials = Dir.glob(File.join(shared_dir, "_*.html.erb"))
|
|
255
229
|
.map { |f| File.basename(f) }
|
|
@@ -263,8 +237,7 @@ module RailsAiContext
|
|
|
263
237
|
|
|
264
238
|
# Helpers — so agents use existing helpers instead of creating new ones
|
|
265
239
|
begin
|
|
266
|
-
|
|
267
|
-
helper_file = File.join(root, "app", "helpers", "application_helper.rb")
|
|
240
|
+
helper_file = File.join(project_root, "app", "helpers", "application_helper.rb")
|
|
268
241
|
if File.exist?(helper_file)
|
|
269
242
|
helper_methods = File.read(helper_file).scan(/def\s+(\w+)/).flatten
|
|
270
243
|
if helper_methods.any?
|