rails-ai-bridge 5.1.0 → 5.2.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 +4 -4
- data/.reek.yml +20 -19
- data/.rubocop.yml +7 -0
- data/AGENTS.md +4 -4
- data/Archspec.rb +53 -27
- data/CHANGELOG.md +144 -1
- data/CLAUDE.md +6 -5
- data/CONTRIBUTING.md +2 -2
- data/GEMINI.md +3 -4
- data/README.md +69 -11
- data/docs/COMPARISON.md +95 -0
- data/docs/EXAMPLES.md +260 -0
- data/docs/GUIDE.md +59 -5
- data/docs/ROADMAP.md +80 -0
- data/docs/{gem-general-improvements.md → archive/gem-general-improvements.md} +1 -1
- data/docs/{review-workflow-report.md → archive/review-workflow-report.md} +15 -15
- data/docs/design/dependency-graph.md +213 -0
- data/docs/design/multi-project-support.md +235 -0
- data/docs/design/prism-confidence-tags.md +214 -0
- data/docs/mcp-registry-submission.md +127 -0
- data/docs/mcp-security.md +52 -0
- data/docs/port-registry-resolution.md +309 -3
- data/docs/skill-registry-guide.md +1 -1
- data/lib/rails_ai_bridge/config/introspection.rb +2 -3
- data/lib/rails_ai_bridge/config/server.rb +7 -0
- data/lib/rails_ai_bridge/configuration.rb +1 -1
- data/lib/rails_ai_bridge/context_provider.rb +0 -1
- data/lib/rails_ai_bridge/database_size.rb +17 -4
- data/lib/rails_ai_bridge/doctor/checkers/http_structured_log_checker.rb +34 -0
- data/lib/rails_ai_bridge/doctor.rb +2 -1
- data/lib/rails_ai_bridge/http_transport_app.rb +0 -1
- data/lib/rails_ai_bridge/introspector/parallel_runner.rb +0 -1
- data/lib/rails_ai_bridge/introspector.rb +4 -7
- data/lib/rails_ai_bridge/introspectors/config_introspector.rb +0 -1
- data/lib/rails_ai_bridge/introspectors/controller_introspector.rb +0 -1
- data/lib/rails_ai_bridge/introspectors/model_introspector.rb +0 -1
- data/lib/rails_ai_bridge/introspectors/model_semantic_classifier.rb +170 -0
- data/lib/rails_ai_bridge/introspectors/path_resolver.rb +313 -0
- data/lib/rails_ai_bridge/introspectors/route_introspector.rb +0 -1
- data/lib/rails_ai_bridge/introspectors/schema_introspector.rb +0 -1
- data/lib/rails_ai_bridge/introspectors/semantic_introspector.rb +0 -1
- data/lib/rails_ai_bridge/registry/message_sanitizer.rb +1 -0
- data/lib/rails_ai_bridge/registry/pack_resolver.rb +0 -3
- data/lib/rails_ai_bridge/registry/rake_presenter.rb +0 -1
- data/lib/rails_ai_bridge/registry.rb +0 -5
- data/lib/rails_ai_bridge/rubydex_adapter/incremental_indexer.rb +1 -1
- data/lib/rails_ai_bridge/rubydex_adapter.rb +0 -4
- data/lib/rails_ai_bridge/serializers/anti_hallucination_rules/section_formatter.rb +21 -0
- data/lib/rails_ai_bridge/serializers/anti_hallucination_rules.rb +62 -0
- data/lib/rails_ai_bridge/serializers/context_file_serializer.rb +35 -19
- data/lib/rails_ai_bridge/serializers/formatters/providers/gemini_footer_formatter.rb +2 -1
- data/lib/rails_ai_bridge/serializers/json_serializer.rb +10 -1
- data/lib/rails_ai_bridge/serializers/markdown_serializer.rb +1 -0
- data/lib/rails_ai_bridge/{tools → serializers}/model_details/non_ar_models_appendix.rb +2 -2
- data/lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb +14 -3
- data/lib/rails_ai_bridge/serializers/providers/claude_rules_serializer.rb +23 -52
- data/lib/rails_ai_bridge/serializers/providers/claude_serializer.rb +0 -1
- data/lib/rails_ai_bridge/serializers/providers/codex_serializer.rb +0 -1
- data/lib/rails_ai_bridge/serializers/providers/codex_support_serializer.rb +11 -12
- data/lib/rails_ai_bridge/serializers/providers/copilot_instructions_serializer.rb +8 -21
- data/lib/rails_ai_bridge/serializers/providers/copilot_serializer.rb +0 -1
- data/lib/rails_ai_bridge/serializers/providers/cursor_rules_serializer.rb +1 -19
- data/lib/rails_ai_bridge/serializers/providers/devin_rules_serializer.rb +3 -21
- data/lib/rails_ai_bridge/serializers/providers/devin_serializer.rb +1 -1
- data/lib/rails_ai_bridge/serializers/providers/gemini_serializer.rb +0 -1
- data/lib/rails_ai_bridge/serializers/providers/rules_orchestrator.rb +0 -1
- data/lib/rails_ai_bridge/serializers/providers/rules_serializer.rb +0 -1
- data/lib/rails_ai_bridge/serializers/rule_file_writer.rb +44 -0
- data/lib/rails_ai_bridge/serializers/shared_assistant_guidance.rb +2 -16
- data/lib/rails_ai_bridge/server.rb +23 -1
- data/lib/rails_ai_bridge/services/context_generation_service.rb +12 -5
- data/lib/rails_ai_bridge/tools/get_model_details.rb +3 -3
- data/lib/rails_ai_bridge/tools/model_details/full_formatter.rb +2 -2
- data/lib/rails_ai_bridge/tools/model_details/standard_formatter.rb +2 -2
- data/lib/rails_ai_bridge/tools/model_details/summary_formatter.rb +2 -2
- data/lib/rails_ai_bridge/tools/query/guard.rb +46 -0
- data/lib/rails_ai_bridge/tools/query/payload_formatter.rb +51 -0
- data/lib/rails_ai_bridge/tools/query.rb +182 -0
- data/lib/rails_ai_bridge/tools/read_logs/log_locator.rb +101 -0
- data/lib/rails_ai_bridge/tools/read_logs.rb +210 -0
- data/lib/rails_ai_bridge/version.rb +1 -1
- data/lib/rails_ai_bridge/view_file_analyzer.rb +1 -1
- data/lib/rails_ai_bridge.rb +2 -1
- data/rails-ai-bridge.gemspec +1 -1
- data/server.json +2 -2
- metadata +22 -9
- data/docs/02-port-registry-resolution.md +0 -152
- data/docs/registry-resolution.md +0 -275
- data/lib/rails_ai_bridge/model_semantic_classifier.rb +0 -168
- data/lib/rails_ai_bridge/path_resolver.rb +0 -311
- data/test_table.md +0 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5b63548b24b25e5ccd6faa5fa898e999bbd750283b36f5e2cd4d27b83d073021
|
|
4
|
+
data.tar.gz: 49088ba707aa54af31f733a61a2d256137a58fd24cc26a4d3a30161bfdc0a10b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9054c6e37be79a49ed71137f308e6c63a9f0be5bc8c0f48f982ad99ddec54dcae518cc3f563b2052164fe7d6972060fceba9ced08e3befdedf473cb1857f3d30
|
|
7
|
+
data.tar.gz: 832b6f1ee08194ac6cc7bce3c36cb616da7ce5d8bf20e51bffb1a56d36957f2ad6cdd00f352ded5d7c87b8b79318f70d406ee8e6b74a08d0d905889908e39a83
|
data/.reek.yml
CHANGED
|
@@ -99,8 +99,8 @@ detectors:
|
|
|
99
99
|
- RailsAiBridge::FreshnessHeader#extract_metadata_for
|
|
100
100
|
- RailsAiBridge::Introspectors::MiddlewareIntrospector#categorize_middleware
|
|
101
101
|
- RailsAiBridge::Mcp::HttpRateLimiter#initialize
|
|
102
|
-
- RailsAiBridge::ModelSemanticClassifier#classify_with_payload
|
|
103
|
-
- RailsAiBridge::ModelSemanticClassifier#classify_without_payload
|
|
102
|
+
- RailsAiBridge::Introspectors::ModelSemanticClassifier#classify_with_payload
|
|
103
|
+
- RailsAiBridge::Introspectors::ModelSemanticClassifier#classify_without_payload
|
|
104
104
|
- RailsAiBridge::Registry::ContextAggregator#aggregate_status
|
|
105
105
|
- RailsAiBridge::Registry::ContextProviderClient#find_tool
|
|
106
106
|
- RailsAiBridge::Registry::PackResolver#initialize
|
|
@@ -197,7 +197,7 @@ detectors:
|
|
|
197
197
|
- RailsAiBridge::Mcp::CacheRateLimiter#increment
|
|
198
198
|
- RailsAiBridge::Mcp::HttpRateLimiter#allow?
|
|
199
199
|
- RailsAiBridge::Mcp::HttpStructuredLog#target_logger
|
|
200
|
-
- RailsAiBridge::ModelSemanticClassifier#call
|
|
200
|
+
- RailsAiBridge::Introspectors::ModelSemanticClassifier#call
|
|
201
201
|
- RailsAiBridge::Registry::ContextAggregator#fetch_all
|
|
202
202
|
- RailsAiBridge::Registry::ContextAggregator#fetch_provider
|
|
203
203
|
- RailsAiBridge::Registry::ContextAggregator#fetch_tool
|
|
@@ -390,7 +390,7 @@ detectors:
|
|
|
390
390
|
- RailsAiBridge::Introspectors::TurboIntrospector#extract_model_broadcasts
|
|
391
391
|
- RailsAiBridge::Introspectors::ViewIntrospector#detect_template_engines
|
|
392
392
|
- RailsAiBridge::Mcp::CacheRateLimiter#fallback_increment
|
|
393
|
-
- RailsAiBridge::PathResolver#path_inside_real_root?
|
|
393
|
+
- RailsAiBridge::Introspectors::PathResolver#path_inside_real_root?
|
|
394
394
|
- RailsAiBridge::Registry::Lockfile#to_json
|
|
395
395
|
- RailsAiBridge::Registry::PackResolver#gather_active_packs
|
|
396
396
|
- RailsAiBridge::Registry::PackResolver#trace_dependency_cycle
|
|
@@ -476,7 +476,7 @@ detectors:
|
|
|
476
476
|
exclude:
|
|
477
477
|
- RailsAiBridge::Generators::InstallGenerator
|
|
478
478
|
- RailsAiBridge::Fingerprinter::CachedSnapshot
|
|
479
|
-
- RailsAiBridge::PathResolver
|
|
479
|
+
- RailsAiBridge::Introspectors::PathResolver
|
|
480
480
|
- RailsAiBridge::RubydexAdapter
|
|
481
481
|
- RailsAiBridge::Serializers::ContextFileSerializer::ManagedRegionLayout
|
|
482
482
|
- RailsAiBridge::Serializers::Providers::ClaudeSerializer
|
|
@@ -592,8 +592,8 @@ detectors:
|
|
|
592
592
|
- RailsAiBridge::Introspectors::SeedsIntrospector#detect_seeded_models
|
|
593
593
|
- RailsAiBridge::Introspectors::TestIntrospector#detect_test_helpers
|
|
594
594
|
- RailsAiBridge::Introspectors::TurboIntrospector#extract_turbo_frames
|
|
595
|
-
- RailsAiBridge::ModelSemanticClassifier#self.through_join_model_names
|
|
596
|
-
- RailsAiBridge::PathResolver#glob_for
|
|
595
|
+
- RailsAiBridge::Introspectors::ModelSemanticClassifier#self.through_join_model_names
|
|
596
|
+
- RailsAiBridge::Introspectors::PathResolver#glob_for
|
|
597
597
|
- RailsAiBridge::Registry::Resolver#build_deprecated_index
|
|
598
598
|
- RailsAiBridge::Registry::Resolver#build_summary_map
|
|
599
599
|
- RailsAiBridge::Registry::Resolver#validate_dependencies
|
|
@@ -644,7 +644,7 @@ detectors:
|
|
|
644
644
|
- RailsAiBridge::Mcp::Auth::Strategies::Jwt#initialize
|
|
645
645
|
- RailsAiBridge::Mcp::Authenticator#call
|
|
646
646
|
- RailsAiBridge::Mcp::HttpStructuredLog#emit
|
|
647
|
-
- RailsAiBridge::PathResolver#max_files_per_path
|
|
647
|
+
- RailsAiBridge::Introspectors::PathResolver#max_files_per_path
|
|
648
648
|
- RailsAiBridge::Registry::Lockfile#load
|
|
649
649
|
- RailsAiBridge::Registry::RakePresenter#initialize
|
|
650
650
|
- RailsAiBridge::Registry::SkillSourceResolver#pull_stale?
|
|
@@ -729,7 +729,7 @@ detectors:
|
|
|
729
729
|
- RailsAiBridge::Introspectors::ModelIntrospector::SourceMacroExtractor
|
|
730
730
|
- RailsAiBridge::Introspectors::ModelIntrospector
|
|
731
731
|
- RailsAiBridge::Introspectors::Schema::StaticStructureSqlParser
|
|
732
|
-
- RailsAiBridge::PathResolver
|
|
732
|
+
- RailsAiBridge::Introspectors::PathResolver
|
|
733
733
|
- RailsAiBridge::RubydexAdapter::IncrementalIndexer
|
|
734
734
|
- RailsAiBridge::RubydexAdapter
|
|
735
735
|
- RailsAiBridge::Serializers::Providers::BaseProviderSerializer
|
|
@@ -869,10 +869,10 @@ detectors:
|
|
|
869
869
|
- RailsAiBridge::Mcp::Authenticator#resolve_strategy
|
|
870
870
|
- RailsAiBridge::Mcp::HttpRateLimiter#allow?
|
|
871
871
|
- RailsAiBridge::Mcp::HttpStructuredLog#emit
|
|
872
|
-
- RailsAiBridge::ModelSemanticClassifier#call
|
|
873
|
-
- RailsAiBridge::ModelSemanticClassifier#metadata_column_names
|
|
874
|
-
- RailsAiBridge::ModelSemanticClassifier#self.through_join_model_names
|
|
875
|
-
- RailsAiBridge::PathResolver#glob_for
|
|
872
|
+
- RailsAiBridge::Introspectors::ModelSemanticClassifier#call
|
|
873
|
+
- RailsAiBridge::Introspectors::ModelSemanticClassifier#metadata_column_names
|
|
874
|
+
- RailsAiBridge::Introspectors::ModelSemanticClassifier#self.through_join_model_names
|
|
875
|
+
- RailsAiBridge::Introspectors::PathResolver#glob_for
|
|
876
876
|
- RailsAiBridge::Registry::FrontmatterParser#self.extract_frontmatter_lines
|
|
877
877
|
- RailsAiBridge::Registry::Lockfile#load
|
|
878
878
|
- RailsAiBridge::Registry::PackResolver#expand_transitive_dependencies
|
|
@@ -963,6 +963,7 @@ detectors:
|
|
|
963
963
|
- RailsAiBridge::Serializers::Providers::CursorRulesSerializer#render_models_rule
|
|
964
964
|
- RailsAiBridge::Serializers::Providers::DevinRulesSerializer#call
|
|
965
965
|
- RailsAiBridge::Serializers::Providers::DevinSerializer#render
|
|
966
|
+
- RailsAiBridge::Serializers::RuleFileWriter#call
|
|
966
967
|
- RailsAiBridge::Serializers::SharedAssistantGuidance#claude_full_footer_lines
|
|
967
968
|
- RailsAiBridge::Serializers::SharedAssistantGuidance#compact_engineering_rules_footer_lines
|
|
968
969
|
- RailsAiBridge::Serializers::SharedAssistantGuidance#cursor_engineering_mdc_body_lines
|
|
@@ -1033,7 +1034,7 @@ detectors:
|
|
|
1033
1034
|
- RailsAiBridge::Tools::ListRegistry::RegistryCatalogFormatter#format_catalog
|
|
1034
1035
|
- RailsAiBridge::Tools::ListRegistry::RegistryCatalogFormatter#format_packs
|
|
1035
1036
|
- RailsAiBridge::Tools::ModelDetails::FullFormatter#call
|
|
1036
|
-
- RailsAiBridge::
|
|
1037
|
+
- RailsAiBridge::Serializers::ModelDetails::NonArModelsAppendix#append_markdown
|
|
1037
1038
|
- RailsAiBridge::Tools::ModelDetails::SingleModelFormatter#append_source_macros
|
|
1038
1039
|
- RailsAiBridge::Tools::ModelDetails::SingleModelFormatter#call
|
|
1039
1040
|
- RailsAiBridge::Tools::ModelDetails::StandardFormatter#call
|
|
@@ -1094,8 +1095,8 @@ detectors:
|
|
|
1094
1095
|
- RailsAiBridge::Mcp::HttpRateLimiter#allow?
|
|
1095
1096
|
- RailsAiBridge::Mcp::HttpRateLimiter#initialize
|
|
1096
1097
|
- RailsAiBridge::Mcp::HttpStructuredLog#emit
|
|
1097
|
-
- RailsAiBridge::ModelSemanticClassifier#call
|
|
1098
|
-
- RailsAiBridge::ModelSemanticClassifier#metadata_column_names
|
|
1098
|
+
- RailsAiBridge::Introspectors::ModelSemanticClassifier#call
|
|
1099
|
+
- RailsAiBridge::Introspectors::ModelSemanticClassifier#metadata_column_names
|
|
1099
1100
|
- RailsAiBridge::Registry::PackResolver#gather_active_packs
|
|
1100
1101
|
- RailsAiBridge::Registry::PackResolver#warn_missing_dependencies
|
|
1101
1102
|
- RailsAiBridge::RubydexAdapter#codebase_stats
|
|
@@ -1244,9 +1245,9 @@ detectors:
|
|
|
1244
1245
|
- RailsAiBridge::Introspectors::StimulusIntrospector#extract_values
|
|
1245
1246
|
- RailsAiBridge::Mcp::Auth::BaseStrategy#extract_bearer
|
|
1246
1247
|
- RailsAiBridge::Mcp::Auth::Strategies::BearerToken#secure_compare
|
|
1247
|
-
- RailsAiBridge::ModelSemanticClassifier#metadata_column_names
|
|
1248
|
-
- RailsAiBridge::ModelSemanticClassifier#safe_column_names
|
|
1249
|
-
- RailsAiBridge::ModelSemanticClassifier#tier
|
|
1248
|
+
- RailsAiBridge::Introspectors::ModelSemanticClassifier#metadata_column_names
|
|
1249
|
+
- RailsAiBridge::Introspectors::ModelSemanticClassifier#safe_column_names
|
|
1250
|
+
- RailsAiBridge::Introspectors::ModelSemanticClassifier#tier
|
|
1250
1251
|
- RailsAiBridge::Registry::PackResolver#auto_load_dependencies?
|
|
1251
1252
|
- RailsAiBridge::Registry::PackResolver#compute_priority
|
|
1252
1253
|
- RailsAiBridge::Registry::PackResolver#default_lockfile
|
data/.rubocop.yml
CHANGED
|
@@ -11,6 +11,13 @@ AllCops:
|
|
|
11
11
|
- "spec/internal/**/*"
|
|
12
12
|
- "gemfiles/**/*"
|
|
13
13
|
- ".mutant.yml"
|
|
14
|
+
# Generated/rails-boilerplate demo files (rails new, db/schema.rb, bin/,
|
|
15
|
+
# config boot files) — rails generators emit double-quoted strings and
|
|
16
|
+
# long blocks by design; keeping them excluded means `rubocop -A` never
|
|
17
|
+
# rewrites files the demo intentionally shows as generated output.
|
|
18
|
+
- "examples/demo_app/bin/**/*"
|
|
19
|
+
- "examples/demo_app/config/**/*"
|
|
20
|
+
- "examples/demo_app/db/**/*"
|
|
14
21
|
Naming/FileName:
|
|
15
22
|
Exclude:
|
|
16
23
|
- "lib/rails-ai-bridge.rb"
|
data/AGENTS.md
CHANGED
|
@@ -8,8 +8,8 @@ committed context files. It does not write to the host database.
|
|
|
8
8
|
- `lib/rails_ai_bridge.rb` — Main entry point, public API (Zeitwerk autoloaded)
|
|
9
9
|
- `lib/rails_ai_bridge/configuration.rb` — User-facing config with presets (:standard, :full)
|
|
10
10
|
- `lib/rails_ai_bridge/introspector.rb` — Orchestrates sub-introspectors
|
|
11
|
-
- `lib/rails_ai_bridge/introspectors/` — Built-in introspector classes; `:standard` preset runs **9**, `:full` runs **27** (see `Configuration::PRESETS`). Registry: `Introspector::BUILTIN_INTROSPECTORS` (includes opt-in symbols
|
|
12
|
-
- `lib/rails_ai_bridge/tools/` —
|
|
11
|
+
- `lib/rails_ai_bridge/introspectors/` — Built-in introspector classes; `:standard` preset runs **9**, `:full` runs **27** (see `Configuration::PRESETS`). Registry: `Introspector::BUILTIN_INTROSPECTORS` (`:full` already includes `non_ar_models`; opt-in-only symbols not in any preset: `database_stats`, `semantic`).
|
|
12
|
+
- `lib/rails_ai_bridge/tools/` — 22 built-in MCP tools using the official mcp SDK (hosts can add more via `additional_tools`)
|
|
13
13
|
- `lib/rails_ai_bridge/serializers/` — Output formatters (claude, claude_rules, codex, cursor_rules, devin, devin_rules, copilot, copilot_instructions, gemini, rules, markdown, JSON)
|
|
14
14
|
- `lib/rails_ai_bridge/resources.rb` — MCP resources (static data AI clients read directly)
|
|
15
15
|
- `lib/rails_ai_bridge/server.rb` — MCP server configuration (stdio + HTTP transports)
|
|
@@ -32,7 +32,7 @@ committed context files. It does not write to the host database.
|
|
|
32
32
|
6. **Diff-aware** — context regeneration skips unchanged files
|
|
33
33
|
7. **Per-assistant serializers** — each AI tool gets tailored output format
|
|
34
34
|
8. **Zeitwerk autoloading** — files loaded on-demand, not all upfront
|
|
35
|
-
9. **Introspector presets** — `:standard` (9 core) default, `:full` (27 introspectors
|
|
35
|
+
9. **Introspector presets** — `:standard` (9 core) default, `:full` (27 introspectors, includes `non_ar_models`) with opt-in extras such as `database_stats` and `semantic` for power users
|
|
36
36
|
10. **MCP auto-discovery** — `.mcp.json` generated by install generator
|
|
37
37
|
11. **Outbound context providers (v5)** — `rails_get_provider_context` fetches from declared external MCP services. Disabled by default, exact host allowlist, read-only tool enforcement, `ToolResultCache::NON_CACHEABLE` exclusion. Separate from local `rails_get_context`.
|
|
38
38
|
12. **Compact by default** — context files ≤150 lines, MCP tools use `detail` parameter (summary/standard/full)
|
|
@@ -50,7 +50,7 @@ Uses combustion gem for testing Rails engine behavior in isolation.
|
|
|
50
50
|
## Conventions
|
|
51
51
|
|
|
52
52
|
- Ruby 3.2+ features OK (pattern matching, etc.)
|
|
53
|
-
- Follow rubocop
|
|
53
|
+
- Follow RuboCop with the project's custom limits (see `.rubocop.yml` — plugins performance/rails/rspec; method length, ABC size and class length limits are deliberately more permissive than the omakase defaults)
|
|
54
54
|
- Every introspector returns a Hash, never raises (wraps errors in `{ error: msg }`)
|
|
55
55
|
- MCP tools return `MCP::Tool::Response` objects per SDK convention
|
|
56
56
|
- All tools prefixed with `rails_` per MCP naming best practices
|
data/Archspec.rb
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
# ArchSpec architecture specification for rails-ai-bridge.
|
|
4
4
|
#
|
|
5
|
-
# Defines
|
|
6
|
-
# follow. Lower layers (config, introspectors, registry, rubydex,
|
|
7
|
-
# must not reach up into transport or tooling layers.
|
|
8
|
-
# forbidden.
|
|
5
|
+
# Defines ten components and the dependency directions the gem is expected to
|
|
6
|
+
# follow. Lower layers (core, config, introspectors, registry, rubydex,
|
|
7
|
+
# serializers) must not reach up into transport or tooling layers.
|
|
8
|
+
# Cross-component cycles are forbidden.
|
|
9
9
|
#
|
|
10
10
|
# Run locally with:
|
|
11
11
|
#
|
|
@@ -15,6 +15,17 @@
|
|
|
15
15
|
|
|
16
16
|
source 'lib/rails_ai_bridge/**/*.rb'
|
|
17
17
|
|
|
18
|
+
# Core primitives — dependency-free value types and pure helpers (Service,
|
|
19
|
+
# Service::Result, ExclusionHelper, DatabaseSize) that every layer may use.
|
|
20
|
+
# Extracted per the #250 diagnosis "durable alternative".
|
|
21
|
+
component :core, in: %w[
|
|
22
|
+
lib/rails_ai_bridge/service.rb
|
|
23
|
+
lib/rails_ai_bridge/service/**/*.rb
|
|
24
|
+
lib/rails_ai_bridge/exclusion_helper.rb
|
|
25
|
+
lib/rails_ai_bridge/database_size.rb
|
|
26
|
+
lib/rails_ai_bridge/service_errors.rb
|
|
27
|
+
]
|
|
28
|
+
|
|
18
29
|
# Configuration layer — user-facing settings and presets.
|
|
19
30
|
# Must stay free of upper-layer dependencies so it can be loaded in isolation.
|
|
20
31
|
component :config, in: %w[
|
|
@@ -31,27 +42,15 @@ component :introspectors, in: %w[
|
|
|
31
42
|
]
|
|
32
43
|
|
|
33
44
|
# Runtime context — supporting infrastructure shared by tools and serializers
|
|
34
|
-
# (context providers, fingerprinting,
|
|
45
|
+
# (context providers, fingerprinting, watcher, tasks, errors).
|
|
35
46
|
component :runtime_context, in: %w[
|
|
36
47
|
lib/rails_ai_bridge/assistant_formats_preference.rb
|
|
37
48
|
lib/rails_ai_bridge/cache_warmer.rb
|
|
38
49
|
lib/rails_ai_bridge/context_provider.rb
|
|
39
|
-
lib/rails_ai_bridge/database_size.rb
|
|
40
|
-
lib/rails_ai_bridge/doctor.rb
|
|
41
|
-
lib/rails_ai_bridge/doctor/**/*.rb
|
|
42
|
-
lib/rails_ai_bridge/engine.rb
|
|
43
|
-
lib/rails_ai_bridge/exclusion_helper.rb
|
|
44
50
|
lib/rails_ai_bridge/fingerprinter.rb
|
|
45
51
|
lib/rails_ai_bridge/fingerprinter/**/*.rb
|
|
46
52
|
lib/rails_ai_bridge/freshness_header.rb
|
|
47
53
|
lib/rails_ai_bridge/instrumentation.rb
|
|
48
|
-
lib/rails_ai_bridge/model_semantic_classifier.rb
|
|
49
|
-
lib/rails_ai_bridge/path_resolver.rb
|
|
50
|
-
lib/rails_ai_bridge/resources.rb
|
|
51
|
-
lib/rails_ai_bridge/service.rb
|
|
52
|
-
lib/rails_ai_bridge/service/**/*.rb
|
|
53
|
-
lib/rails_ai_bridge/service_errors.rb
|
|
54
|
-
lib/rails_ai_bridge/services/**/*.rb
|
|
55
54
|
lib/rails_ai_bridge/tasks/**/*.rb
|
|
56
55
|
lib/rails_ai_bridge/tool_result_cache.rb
|
|
57
56
|
lib/rails_ai_bridge/view_file_analyzer.rb
|
|
@@ -59,7 +58,20 @@ component :runtime_context, in: %w[
|
|
|
59
58
|
lib/rails_ai_bridge/watcher/**/*.rb
|
|
60
59
|
]
|
|
61
60
|
|
|
62
|
-
#
|
|
61
|
+
# Host integration — Rails engine wiring, diagnostics, MCP resources that
|
|
62
|
+
# AI clients read directly, plus service orchestrators that sit above the
|
|
63
|
+
# formatting and transport layers. Entry-point glue: it may use every other
|
|
64
|
+
# component (engine wires middleware, doctor checkers reach downward, service
|
|
65
|
+
# orchestrators call serializers); nothing may depend on it. The gem entry
|
|
66
|
+
# point (lib/rails_ai_bridge.rb) sits outside all components.
|
|
67
|
+
component :host_integration, in: %w[
|
|
68
|
+
lib/rails_ai_bridge/engine.rb
|
|
69
|
+
lib/rails_ai_bridge/doctor.rb
|
|
70
|
+
lib/rails_ai_bridge/doctor/**/*.rb
|
|
71
|
+
lib/rails_ai_bridge/services/**/*.rb
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
# MCP tools — the 20 built-in tools exposed over the MCP protocol.
|
|
63
75
|
component :tools, in: 'lib/rails_ai_bridge/tools/**/*.rb'
|
|
64
76
|
|
|
65
77
|
# Output formatters — serialize introspection payloads to per-assistant files.
|
|
@@ -73,12 +85,15 @@ component :registry, in: %w[
|
|
|
73
85
|
lib/rails_ai_bridge/registry/**/*.rb
|
|
74
86
|
]
|
|
75
87
|
|
|
76
|
-
# MCP transport — the server, Rack middleware, HTTP app,
|
|
88
|
+
# MCP transport — the server, Rack middleware, HTTP app, auth/rate-limiting, and
|
|
89
|
+
# the MCP resources registry (resources are part of the MCP protocol surface;
|
|
90
|
+
# Server wires Resources at construction).
|
|
77
91
|
component :mcp_transport, in: %w[
|
|
78
92
|
lib/rails_ai_bridge/server.rb
|
|
79
93
|
lib/rails_ai_bridge/middleware.rb
|
|
80
94
|
lib/rails_ai_bridge/http_transport_app.rb
|
|
81
95
|
lib/rails_ai_bridge/mcp/**/*.rb
|
|
96
|
+
lib/rails_ai_bridge/resources.rb
|
|
82
97
|
]
|
|
83
98
|
|
|
84
99
|
# Rubydex integration — optional semantic code analysis adapter.
|
|
@@ -90,22 +105,33 @@ component :rubydex, in: %w[
|
|
|
90
105
|
|
|
91
106
|
# --- Dependency direction rules ---
|
|
92
107
|
|
|
93
|
-
#
|
|
94
|
-
|
|
108
|
+
# Core is the bottom of the stack; every layer may use it, it uses nothing.
|
|
109
|
+
core.cannot_use :config, :introspectors, :runtime_context, :tools, :serializers,
|
|
110
|
+
:registry, :mcp_transport, :rubydex, :host_integration
|
|
111
|
+
|
|
112
|
+
# Config sits directly above core; it must not reach up into any upper layer.
|
|
113
|
+
config.cannot_use :runtime_context, :tools, :serializers, :mcp_transport, :introspectors,
|
|
114
|
+
:host_integration
|
|
115
|
+
|
|
116
|
+
# Runtime context, tools, and transport sit below host integration wiring;
|
|
117
|
+
# they must not reach up into it.
|
|
118
|
+
runtime_context.cannot_use :host_integration
|
|
119
|
+
tools.cannot_use :host_integration
|
|
120
|
+
mcp_transport.cannot_use :host_integration
|
|
95
121
|
|
|
96
122
|
# Registry and rubydex are leaf adapters; they must not depend on the
|
|
97
123
|
# tooling, formatting, or transport layers.
|
|
98
|
-
registry.cannot_use :tools, :serializers, :mcp_transport
|
|
99
|
-
rubydex.cannot_use :tools, :serializers, :mcp_transport
|
|
124
|
+
registry.cannot_use :tools, :serializers, :mcp_transport, :host_integration
|
|
125
|
+
rubydex.cannot_use :tools, :serializers, :mcp_transport, :host_integration
|
|
100
126
|
|
|
101
127
|
# Introspectors produce plain data and must not depend on tools, formatters,
|
|
102
128
|
# or transport.
|
|
103
|
-
introspectors.cannot_use :tools, :serializers, :mcp_transport
|
|
129
|
+
introspectors.cannot_use :tools, :serializers, :mcp_transport, :host_integration
|
|
104
130
|
|
|
105
131
|
# Serializers format data handed to them; they must not invoke introspection
|
|
106
132
|
# or reach into the transport layer.
|
|
107
|
-
serializers.cannot_use :introspectors, :mcp_transport
|
|
133
|
+
serializers.cannot_use :introspectors, :mcp_transport, :host_integration
|
|
108
134
|
|
|
109
135
|
# Cross-component cycles are forbidden across all defined components.
|
|
110
|
-
no_cycles among: %i[config introspectors runtime_context tools serializers
|
|
111
|
-
registry mcp_transport rubydex]
|
|
136
|
+
no_cycles among: %i[core config introspectors runtime_context tools serializers
|
|
137
|
+
registry mcp_transport rubydex host_integration]
|
data/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,150 @@ 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
|
-
## [
|
|
8
|
+
## [5.2.1] - 2026-09-23
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Updated the GitHub Pages documentation workflow to `actions/upload-pages-artifact@v5`
|
|
13
|
+
and `actions/deploy-pages@v5` (Dependabot PRs #289 and #290).
|
|
14
|
+
- Updated mutation testing to `mutant-rspec` 0.17.0 and refreshed its lockfile
|
|
15
|
+
to current compatible releases, including `mcp` 1.6.0. Refreshed the demo
|
|
16
|
+
app lockfile as well; runtime dependency requirements are unchanged.
|
|
17
|
+
|
|
18
|
+
## [5.2.0] - 2026-09-14
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- `rails ai:doctor` warns when HTTP MCP is auto-mounted (`config.auto_mount`)
|
|
23
|
+
but `config.mcp.http_log_json` is still false, so 401/403/429/handled
|
|
24
|
+
outcomes from `HttpTransportApp` would not emit structured JSON lines.
|
|
25
|
+
- **Anti-hallucination rules in every generated context file (#252/#253/#254).** All
|
|
26
|
+
generated outputs now carry a shared verify-before-write block (heading
|
|
27
|
+
`## Anti-hallucination rules`, rendered by the single
|
|
28
|
+
`RailsAiBridge::Serializers::AntiHallucinationRules` collaborator and controlled by
|
|
29
|
+
`config.output.anti_hallucination_rules`, default `true`): the 7 main context files
|
|
30
|
+
(`CLAUDE.md`, `AGENTS.md`, `.cursorrules`, `.devinrules`, `.github/copilot-instructions.md`,
|
|
31
|
+
`GEMINI.md`, and `.ai-context.json`, which gains an `anti_hallucination_rules` array
|
|
32
|
+
key) plus the 5 split-rules serializers (`.claude/rules/`, `.cursor/rules/`,
|
|
33
|
+
`.devin/rules/`, `.codex/`, `.github/instructions/`). The block sits near the top —
|
|
34
|
+
after the freshness header / document intro — so compact-mode trimming and Devin's
|
|
35
|
+
character cap cannot drop it, and it is always inside the managed region when
|
|
36
|
+
`config.output.managed_region` is enabled.
|
|
37
|
+
- **`rails_query` MCP tool** — runs a single read-only SELECT statement on the app's established ActiveRecord connection. SELECT-only allowlist (CTEs rejected in v1), single-statement enforcement, hard 100-row cap, 5-second statement timeout, and credential-like column redaction via `MessageSanitizer`. Errors follow the `{ error }` contract.
|
|
38
|
+
- **`rails_read_logs` MCP tool** — returns a redacted tail of a log file under `Rails.root/log`. Traversal-safe path allowlist (expanded-path prefix check), 400-line and 2000-byte-per-line caps, `summary`/`standard`/`full` detail levels, and `MessageSanitizer` redaction on every line.
|
|
39
|
+
- Built-in MCP tools: 20 → 22. Both data-access tools are documented in `docs/mcp-security.md`.
|
|
40
|
+
- MCP Registry submission readiness: `server.json` passes
|
|
41
|
+
`mcp-publisher validate` (verification steps and captured output in
|
|
42
|
+
`docs/mcp-registry-submission.md`), plus that guide's exact maintainer
|
|
43
|
+
publish steps (fixes #261).
|
|
44
|
+
- Hosted YARD API documentation: a `docs` workflow publishes generated
|
|
45
|
+
YARD docs to GitHub Pages on every `v*` tag push (same checkout/setup-ruby
|
|
46
|
+
pinning style as the existing workflows, reuses the `docs:yard` coverage
|
|
47
|
+
gate); README gains an "API Documentation" link (fixes #262).
|
|
48
|
+
- Positioning page `docs/COMPARISON.md` comparing rails-ai-bridge with
|
|
49
|
+
rails-ai-context, rails-mcp-server, woods, and rails-hyperdrive
|
|
50
|
+
(feature table, download counts, when-to-choose-which), plus a short
|
|
51
|
+
"How it compares" section in the README (fixes #263).
|
|
52
|
+
- Runnable example app under `examples/demo_app` — a minimal Rails 8 app
|
|
53
|
+
(3 models, 3 controllers, 3 tables) that boots without a database and
|
|
54
|
+
demonstrates install, context generation for all 7 assistant targets, and
|
|
55
|
+
MCP tool calls against the static schema parser. `docs/EXAMPLES.md` walks
|
|
56
|
+
through it with real captured output (fixes #260).
|
|
57
|
+
|
|
58
|
+
### Changed
|
|
59
|
+
|
|
60
|
+
- **`rails_query` and `rails_read_logs` are now opt-in and disabled by default**
|
|
61
|
+
via `config.enable_data_tools` (default `false`). Both tools read live
|
|
62
|
+
application data — `rails_query` runs on the app's database connection and can
|
|
63
|
+
read tables excluded from MCP introspection, and `rails_read_logs` returns raw
|
|
64
|
+
log contents — so an upgrade no longer registers them silently. To keep using
|
|
65
|
+
them after upgrading, set `config.enable_data_tools = true` in the
|
|
66
|
+
`rails_ai_bridge` initializer. See `docs/mcp-security.md` for the residual
|
|
67
|
+
risks (best-effort keyword guard on non-PostgreSQL adapters, best-effort
|
|
68
|
+
redaction that column aliases can bypass).
|
|
69
|
+
- `rails_query` redaction: values under credential-like columns (including
|
|
70
|
+
`password_digest`, `encrypted_password`, `secret_access_key`) are now replaced
|
|
71
|
+
with `[redacted]` unconditionally instead of only when the value itself looks
|
|
72
|
+
secret-like. Non-credential author-metadata columns (`author`, `author_id`)
|
|
73
|
+
keep their values; `authorization`-style columns are redacted.
|
|
74
|
+
- `rails_query` keyword guard now also rejects MySQL `LOCK IN SHARE MODE`
|
|
75
|
+
(alongside the existing `FOR UPDATE`/`FOR SHARE` and `SELECT ... INTO`
|
|
76
|
+
rejections). On PostgreSQL, execution runs inside `SET TRANSACTION READ ONLY`
|
|
77
|
+
with `SET LOCAL statement_timeout`; on other adapters the Ruby
|
|
78
|
+
`Timeout.timeout` fallback remains a documented residual risk.
|
|
79
|
+
- `rails_read_logs` streams the log file in a single bounded pass instead of
|
|
80
|
+
materializing the whole file into memory (tail buffer stays capped at
|
|
81
|
+
`MAX_LINES`), scrubs invalid UTF-8 at the per-line byte cap (replacement
|
|
82
|
+
characters instead of `invalid byte sequence in UTF-8` errors), and returns
|
|
83
|
+
sanitized error responses without writing to the application log. The
|
|
84
|
+
internal-only `ReadLogs.respond`, `error_response`, and `execution_failure`
|
|
85
|
+
helpers are private class methods.
|
|
86
|
+
- `rails_query` now requires the statement to start with `SELECT` (leading
|
|
87
|
+
whitespace only). `EXPLAIN`, `SHOW`, `VALUES`, comment-prefixed SQL, and
|
|
88
|
+
other non-SELECT verbs are rejected. On PostgreSQL the tool uses
|
|
89
|
+
`SET LOCAL statement_timeout` plus `SET TRANSACTION READ ONLY` instead of
|
|
90
|
+
Ruby `Timeout.timeout`. Other adapters keep the Ruby timeout.
|
|
91
|
+
- Compact Claude and Gemini output previously placed the anti-hallucination block in the
|
|
92
|
+
footer under the heading `## Anti-hallucination`; it now uses the consistent named
|
|
93
|
+
section (`## Anti-hallucination rules`) at the top of the file. The rule lines are
|
|
94
|
+
unchanged.
|
|
95
|
+
- **Architecture: broke the 6-component dependency cycle (#250).** Extracted a
|
|
96
|
+
dependency-free `:core` component (`Service`, `Service::Result`,
|
|
97
|
+
`ServiceErrors`, `ExclusionHelper`, `DatabaseSize`); introduced a
|
|
98
|
+
`host_integration` component for `engine.rb`, `doctor/**`, and the service
|
|
99
|
+
orchestrators (`services/**`); grouped `resources.rb` under `mcp_transport`
|
|
100
|
+
(resources are part of the MCP protocol surface that `Server` wires at
|
|
101
|
+
construction). Moved `NonArModelsAppendix` to
|
|
102
|
+
`RailsAiBridge::Serializers::ModelDetails::NonArModelsAppendix`,
|
|
103
|
+
`PathResolver` and `ModelSemanticClassifier` to
|
|
104
|
+
`RailsAiBridge::Introspectors::` (`PathResolver` is now
|
|
105
|
+
`RailsAiBridge::Introspectors::PathResolver`), and `ModelSemanticClassifier`
|
|
106
|
+
to `RailsAiBridge::Introspectors::ModelSemanticClassifier`. Removed the
|
|
107
|
+
`RailsAiBridge::Service` superclass from
|
|
108
|
+
`RubydexAdapter::IncrementalIndexer` (duck-types the Result contract) and
|
|
109
|
+
gave `ContextFileSerializer` a caller-supplied required `fingerprint:` kwarg
|
|
110
|
+
(`ContextGenerationService` computes and passes it; custom serializer
|
|
111
|
+
classes must now accept `fingerprint:`; the remaining write options
|
|
112
|
+
(`format:`, `split_rules:`, `on_conflict:`, `managed_region:`) are accepted
|
|
113
|
+
as a `**write_options` group). `ContextGenerationService.call` no longer
|
|
114
|
+
takes a `fingerprint:` override — the fingerprint is always computed at
|
|
115
|
+
call time; inject one via `.new`. Unknown serializer write options now
|
|
116
|
+
raise `ArgumentError` (matching the previous explicit-keyword behavior).
|
|
117
|
+
The archspec todo baseline and all
|
|
118
|
+
36 inline `archspec:disable` suppressions are gone;
|
|
119
|
+
`bundle exec archspec check` reports zero violations.
|
|
120
|
+
- **Docs cleanup (#246).** README quick start no longer says the gem is
|
|
121
|
+
"once published" (it ships on RubyGems as 5.1.0). The three registry/port
|
|
122
|
+
planning docs are consolidated into the canonical
|
|
123
|
+
`docs/port-registry-resolution.md` (as-built record + user-facing
|
|
124
|
+
"Registry Resolution Reference"); `docs/02-port-registry-resolution.md` and
|
|
125
|
+
`docs/registry-resolution.md` are deleted. Completed planning docs
|
|
126
|
+
`docs/gem-general-improvements.md` and `docs/review-workflow-report.md`
|
|
127
|
+
moved to `docs/archive/`. Junk file `test_table.md` removed.
|
|
128
|
+
- **Docs truth (#247).** AGENTS.md, CLAUDE.md, and CONTRIBUTING.md no longer
|
|
129
|
+
claim the project follows the `rubocop-rails-omakase` style — `.rubocop.yml`
|
|
130
|
+
uses its own custom limits (performance/rails/rspec plugins; method length,
|
|
131
|
+
ABC size and class length limits deliberately more permissive). AGENTS.md
|
|
132
|
+
and CLAUDE.md no longer describe `non_ar_models` as opt-in-only — it ships
|
|
133
|
+
in the `:full` preset; only `database_stats` and `semantic` are opt-in-only
|
|
134
|
+
(fixed the same claim in the `Introspector::BUILTIN_INTROSPECTORS` YARD
|
|
135
|
+
comment). `doc_parity_spec.rb` gains guard examples for both claims.
|
|
136
|
+
|
|
137
|
+
### Fixed
|
|
138
|
+
|
|
139
|
+
- `DatabaseSize.bucket` and `DatabaseSize.bucket_for_table` no longer classify
|
|
140
|
+
invalid row counts as the `hot` bucket. Negative counts, including negative
|
|
141
|
+
fractional counts (e.g. stale or unanalyzed PostgreSQL statistics sentinels),
|
|
142
|
+
and non-numeric values now return `nil` instead of being bucketed as `hot`
|
|
143
|
+
(fallback) or `small` (`to_i` truncation/coercion). Callers already treat
|
|
144
|
+
`nil` as "no size data".
|
|
145
|
+
- `server.json` no longer drifts from the released gem: its `version` now
|
|
146
|
+
matches `RailsAiBridge::VERSION` (was stale at `3.0.0`) and the description
|
|
147
|
+
reports the real 20 read-only tools (was 13). `CONTRIBUTING.md`, `GEMINI.md`,
|
|
148
|
+
and `docs/GUIDE.md` tool counts corrected from 19 to 20; `GEMINI.md` also
|
|
149
|
+
documents the `:full` preset as 27 introspectors (was a corrupted 26/27
|
|
150
|
+
mix). Parity and release-consistency specs now guard the `server.json`
|
|
151
|
+
version and tool counts (fixes #245).
|
|
9
152
|
|
|
10
153
|
## [5.1.0] - 2026-09-11
|
|
11
154
|
|
data/CLAUDE.md
CHANGED
|
@@ -10,9 +10,10 @@ committed context files. It does not write to the host database.
|
|
|
10
10
|
- `lib/rails_ai_bridge/introspector.rb` — Orchestrates sub-introspectors
|
|
11
11
|
- `lib/rails_ai_bridge/introspectors/` — Built-in introspector classes; `:standard` preset
|
|
12
12
|
runs **9**, `:full` runs **27** (see `Configuration::PRESETS`). Registry:
|
|
13
|
-
`Introspector::BUILTIN_INTROSPECTORS` (
|
|
14
|
-
`
|
|
15
|
-
|
|
13
|
+
`Introspector::BUILTIN_INTROSPECTORS` (`:full` already includes
|
|
14
|
+
`non_ar_models`; opt-in-only symbols not in any preset: `database_stats`,
|
|
15
|
+
`semantic`).
|
|
16
|
+
- `lib/rails_ai_bridge/tools/` — 22 built-in MCP tools using the official mcp SDK
|
|
16
17
|
(hosts can add more via `additional_tools`)
|
|
17
18
|
- `lib/rails_ai_bridge/serializers/` — Output formatters (claude, claude_rules,
|
|
18
19
|
codex, cursor_rules, devin, devin_rules, copilot, copilot_instructions,
|
|
@@ -38,7 +39,7 @@ committed context files. It does not write to the host database.
|
|
|
38
39
|
6. **Diff-aware** — context regeneration skips unchanged files
|
|
39
40
|
7. **Per-assistant serializers** — each AI tool gets tailored output format
|
|
40
41
|
8. **Zeitwerk autoloading** — files loaded on-demand, not all upfront
|
|
41
|
-
9. **Introspector presets** — `:standard` (9 core) default, `:full` (27 introspectors
|
|
42
|
+
9. **Introspector presets** — `:standard` (9 core) default, `:full` (27 introspectors, includes `non_ar_models`) with opt-in extras such as `database_stats` and `semantic` for power users
|
|
42
43
|
10. **MCP auto-discovery** — `.mcp.json` generated by install generator
|
|
43
44
|
11. **Outbound context providers (v5)** — `rails_get_provider_context` fetches from declared external MCP services. Disabled by default, exact host allowlist, read-only tool enforcement, `ToolResultCache::NON_CACHEABLE` exclusion. Separate from local `rails_get_context`.
|
|
44
45
|
12. **Compact by default** — context files ≤150 lines, MCP tools use `detail` parameter (summary/standard/full)
|
|
@@ -56,7 +57,7 @@ Uses combustion gem for testing Rails engine behavior in isolation.
|
|
|
56
57
|
## Conventions
|
|
57
58
|
|
|
58
59
|
- Ruby 3.2+ features OK (pattern matching, etc.)
|
|
59
|
-
- Follow rubocop
|
|
60
|
+
- Follow RuboCop with the project's custom limits (see `.rubocop.yml` — plugins performance/rails/rspec; method length, ABC size and class length limits are deliberately more permissive than the omakase defaults)
|
|
60
61
|
- Every introspector returns a Hash, never raises (wraps errors in `{ error: msg }`)
|
|
61
62
|
- MCP tools return `MCP::Tool::Response` objects per SDK convention
|
|
62
63
|
- All tools prefixed with `rails_` per MCP naming best practices
|
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_bridge/
|
|
21
21
|
├── introspectors/ # Built-in introspectors (schema, models, non_ar_models, routes, …)
|
|
22
|
-
├── tools/ #
|
|
22
|
+
├── tools/ # 22 built-in MCP tools (detail levels, pagination, extensible)
|
|
23
23
|
├── rubydex_adapter.rb # Rubydex API wrapper (singleton + query interface + stats)
|
|
24
24
|
├── rubydex_adapter/ # Extracted collaborators (one concern each)
|
|
25
25
|
│ ├── serializer.rb # Hash serialization (declaration_to_hash, definition_to_hash, …)
|
|
@@ -49,7 +49,7 @@ lib/rails_ai_bridge/
|
|
|
49
49
|
|
|
50
50
|
## Code Style
|
|
51
51
|
|
|
52
|
-
- Follow `
|
|
52
|
+
- Follow RuboCop with the project's custom limits (see `.rubocop.yml` — plugins performance/rails/rspec; method length, ABC size and class length limits are deliberately more permissive than the omakase defaults); run `bundle exec rubocop`
|
|
53
53
|
- Optional complexity check: `bundle exec skunk lib/rails_ai_bridge/…` (gem in `:development`/`:test`) — keep new or refactored files lean (project goal: Skunk score around **≤ 25** where practical).
|
|
54
54
|
|
|
55
55
|
- Ruby 3.2+ features welcome (pattern matching, etc.)
|
data/GEMINI.md
CHANGED
|
@@ -8,10 +8,9 @@ committed context files. It does not write to the host database.
|
|
|
8
8
|
- `lib/rails_ai_bridge.rb` — Main entry point, public API (Zeitwerk autoloaded)
|
|
9
9
|
- `lib/rails_ai_bridge/configuration.rb` — User-facing config with presets (:standard, :full)
|
|
10
10
|
- `lib/rails_ai_bridge/introspector.rb` — Orchestrates sub-introspectors
|
|
11
|
-
- `lib/rails_ai_bridge/introspectors/` — Built-in introspector classes; `:standard` preset runs **9**, `:full` runs **
|
|
12
|
-
- `lib/rails_ai_bridge/tools/` —
|
|
13
|
-
- `lib/rails_ai_bridge/serializers/` — Output formatters (claude, claude_rules, cursor_rules,
|
|
14
|
-
runs **9**, `:full` runs **27** (see `Configuration::PRESETS`). Registry:
|
|
11
|
+
- `lib/rails_ai_bridge/introspectors/` — Built-in introspector classes; `:standard` preset runs **9**, `:full` runs **27** (see `Configuration::PRESETS`). Registry: `Introspector::BUILTIN_INTROSPECTORS` (includes opt-in symbols such as `database_stats`, `non_ar_models` not listed in those presets).
|
|
12
|
+
- `lib/rails_ai_bridge/tools/` — 22 built-in MCP tools using the official mcp SDK (hosts can add more via `additional_tools`)
|
|
13
|
+
- `lib/rails_ai_bridge/serializers/` — Output formatters (claude, claude_rules, codex, cursor_rules, devin, devin_rules, copilot, copilot_instructions, gemini, rules, markdown, JSON)
|
|
15
14
|
- `lib/rails_ai_bridge/resources.rb` — MCP resources (static data AI clients read directly)
|
|
16
15
|
- `lib/rails_ai_bridge/server.rb` — MCP server configuration (stdio + HTTP transports)
|
|
17
16
|
- `lib/rails_ai_bridge/middleware.rb` — Rack middleware for auto-mounting MCP HTTP endpoint
|