Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[4.1.0] - 2026-08-11
Added
- JWT authentication docs for the HTTP MCP transport (#129) —
docs/mcp-security.mdnow documents themcp_jwt_decoderpattern with a workedJWT.decodeexample, the decoder return-value contract, and a token rotation strategy (short expiry, signing-key overlap windows, revocation guidance). rails_use_skill/rails_use_agentMCP tools (#133) — resolve a skill or agent viaRegistry::Resolverand return it framed for immediate in-context application: an intent header, the deprecation notice when the name was redirected, the full content, and a follow-through footer. Use these to act on a skill;rails_resolve_skillremains the read-only inspection tool (withpack=pinning).- JSON output for the registry rake tasks (#128) —
rails "ai:skills:list[json]"(orFORMAT=json rails ai:skills:list) prints a stable{"packs": [...], "skills": [...]}catalog document for CI and custom tooling.RakePresentergainsskills_json,packs_json, andcatalog_json; the default table output is unchanged. - Transitive
depends_onloading for skill packs (#126) — opt in withconfig.registry.auto_load_dependencies = true(defaultfalse):PackResolverexpands declared pack dependencies transitively (fixed-point iteration capped at 10 levels) and warns about circular dependency chains while still loading every pack in the cycle. Dependencies missing from the manifest are left to the existing warning, which now points at the new flag. - Structured logging for registry git operations (#131) —
SkillSourceResolveraccepts an optionallogger:(defaults toRails.logger, or a stderr logger outside Rails). Clone, pull, and checkout operations logkey=valuelines: DEBUG before the operation, INFO withduration_mson success, ERROR with the failure message before raising. - Context provider definitions in the registry manifest (#134) — new
Registry::ContextProviderDefinitionandRegistry::ContextToolSpecvalue objects (ported from the Rust runtime) parse an optionalcontext_providerssection of the registry manifest: providertype/endpoint, optional flag, and tool lists supporting both simple names and{ name, field, arguments }mappings.RegistryManifest#context_providersdefaults to{}— parsing is preparatory and nothing consumes these definitions yet. - Manifest schema validation (#123) — new
RegistryManifest.validate!raises a descriptiveRegistryManifest::ValidationErrorfor the first invalid field (missing/empty packsource; wrong types forversion,default_stack,ref,tile,depends_on,always_loaded,priority; non-objectpacksentries). Newrails ai:registry:validaterake task validates the configured manifest for CI/pre-commit use and exits non-zero on failure.
Changed (breaking)
- Full SHA-256 digests for skill-pack cache keys (#122) —
SkillSourceResolver.compute_cache_keynow appends the full 64-character SHA-256 hex digest instead of a 16-character truncation, consistent with the gem's fingerprinting. Cache directories created under the old key format are orphaned; clear~/.rails-ai-bridge/cacheto reclaim disk space.
[4.0.0] - 2026-08-09
Changed (breaking)
mcpgem raised to 1.x (#104/#118) — gemspec now requiresmcp >= 1.0, < 2.0(was>= 0.25, < 1.0). Full suite green on mcp 1.1.0 with no production code changes; characterization specs inspec/lib/rails_ai_bridge/mcp/sdk_compatibility_spec.rb. Hosts must runbundle update mcpafter upgrading. See UPGRADING.md for details.
Fixed
- Ruby 4.0 test timing (#104/#118) — ReDoS and perf specs use
Process.clock_gettimeinstead of thebenchmarkgem (no longer a default gem on Ruby 4.0+).
[3.7.0] - 2026-08-08
Added
- Managed regions preserve hand-authored content in provider files (#98/#119) — opt in with
config.output.managed_region = true(orMERGE=1 rails ai:bridge) and generated context is confined to a<!-- BEGIN rails-ai-bridge: … -->/<!-- END rails-ai-bridge -->block. Prose written above or below the block survives every regeneration. A pre-existing hand-authored file gets the block appended rather than clobbered; a file this gem previously generated (detected via its leading freshness header) is replaced, so opting in never leaves a stale second copy of the context above the block. Markdown provider files only (CLAUDE.md,AGENTS.md,GEMINI.md,.github/copilot-instructions.md,.cursorrules,.devinrules);.ai-context.jsonnever receives markers. Default behavior is unchanged — files are still rewritten in full unless you opt in. ai:doctorreads freshness from inside the managed region (#98/#119) — files whose freshness header is preceded by hand-authored prose are no longer misreported as stale..ai-context.jsonis still read whole, since it never carries markers.
Fixed
- Decoupled
ManagedRegionLayoutfromFreshnessHeader::HEADER_PATTERN(#120) — extracted a publicFreshnessHeader.gem_generated?predicate so the layout doesn't reach into a private constant. Memoizedwhole_file_outputto avoid duplicate header checks per write cycle. - Trailing blank lines on append (#120) —
ManagedRegion.mergenow usesrstripinstead ofchomp, so appending to a file with multiple trailing newlines doesn't produce extra blank lines. - Documented marker edge cases (#120) — README now warns about marker-shaped lines in hand-authored prose and about deleting both markers.
[3.6.2] - 2026-08-07
Added
structure.sqlsupport in offline/static schema introspection (#96/#97/#116) — apps usingconfig.active_record.schema_format = :sql(nodb/schema.rb) now get table, column, index, and foreign-key context offline viaIntrospectors::Schema::StaticStructureSqlParser. The live-connection path was already format-agnostic. Output shape matches the live introspector so formatters work unchanged. Partition-child tables (CREATE TABLE … PARTITION OF …) are not expanded (follow-up).
Fixed
ai:doctorschema check forschema_format = :sql(#96/#97/#116) — Schema check passes whendb/structure.sqlis present; fix hint points atrails db:migrate(orrails db:schema:dump).
[3.6.1] - 2026-08-07
Security
- Skill-pack git URL scheme allowlist (#105/#110) —
DefaultGitRunner#clone_repoaccepts onlyhttps://, SCP-stylegit@host:path, andssh://. Rejectsfile://, plainhttp://, and empty URLs. ValidationArgumentErrors do not interpolate the raw URL, so credentials in userinfo cannot leak via exception messages. - SECURITY.md supported-versions table (#106/#112) — documents 3.6.x / 3.5.x as supported, best-effort for older 3.x, and end-of-life for 1.x / 2.x.
- Residual MCP HTTP risk checklist (#107/#113) — operator checklist in
docs/mcp-security.md(open HTTP default, CORS*, in-memory rate limit) with an install-generator pointer.
Changed
rubydexbumped to~> 0.3.0(#103/#111) — was~> 0.2.9. Runbundle update rubydexin host apps.- Dependency audit (2026-08) (#99) —
bundle-auditclean; officialmcpremains on 0.25.x (< 1.0). Migration tomcp1.x remains open in #104.
[3.6.0]
Changed
mcpminimum version raised to 0.25 (#92) — the gemspec lower bound is now>= 0.25(was>= 0.10), matching the minimum version the codebase actually requires. The upper bound remains< 1.0.rubydexconstraint tightened to~> 0.2.9(#92) — was~> 0.2.4. This is a minor breaking change for users pinned to rubydex 0.2.4–0.2.8; update your lockfile withbundle update rubydex.simplecovbumped to 1.0 (#92) — development dependency only; does not affect gem consumers. The test suite filter was migrated fromadd_filter '/spec/'toskip 'spec'per the simplecov 1.0 migration guide (SourceFile#project_filenameno longer includes a leading separator).
Fixed
Style/ArrayIntersectlint offense (#91/#92) — pre-existing rubocop offense incontext_summary.rbautocorrected to useArray#intersect?. No behavior change.
Added
- PathResolver architectural documentation (#90/#91) — class-level docblock documents PathResolver's intentional role as a shared utility (11 introspector callers, high betweenness centrality). Prevents false "god class" flags from future graph analyses.
- PathResolver edge-case tests (#90/#91) — 6 new specs covering the private
SafeRelativePath(backslash normalization, Windows path rejection, empty path rejection) andSafeJoin(valid joins, traversal escape prevention) helper classes.
[3.5.2]
Security
- HTTP MCP unauthenticated boot warning (#60/#81) — the standalone HTTP MCP server now prints a one-time stderr warning when it boots in a non-production environment without an authentication strategy, making the default open behavior visible.
- Pluggable / distributed rate limiting (#69/#80) —
config.mcp.rate_limiteraccepts any object implementingallow?(ip)orcall(ip), enabling shared backends such as Redis orRails.cache. A built-inMcp::CacheRateLimiteris provided for multi-process Puma deployments. - Skill pack lockfile verification (#65/#84) —
config/rails_ai_bridge/directory.lockrecords the expected git commit SHA for every remote skill pack.PackResolvercompares the cloned HEAD against the lockfile and fails closed on mismatch. Generate or update the lockfile withrails ai:registry:lockfile. Verification mode is configurable viaconfig.registry.lockfile_verification(:strict,:warn,:disabled). - Security documentation (#61/#62/#82/#83) — added distributed rate-limiting guidance, a stdio transport threat model, and operational hardening recommendations.
Added
- CORS support for HTTP MCP (#63/#76) —
config.mcp.cors_originscontrolsAccess-Control-Allow-Originheaders for the MCP HTTP endpoint;['*']or a list of exact origins is supported. - JSON output for MCP tools (#68/#77) —
rails_get_routesandrails_get_model_detailsnow acceptformat: 'json'for programmatic clients. authorizelambda logging (#64/#75) — explicit denies and lambda exceptions on the HTTP MCP path are now logged and emitted throughMcp::HttpStructuredLog.bundler-auditCI job (#74/#78) — the GitHub Actions workflow now runsbundle-audit update && bundle-audit checkto catch known vulnerable dependencies.- MCP tool result caching (#71/#79) — opt-in TTL-based cache keyed by tool name + SHA256 fingerprint of arguments. Enable with
config.mcp.tool_result_cache_ttl(default0). - ActiveSupport::Notifications hooks (#72/#85) — emits
rails_ai_bridge.tool.call,rails_ai_bridge.tool.result_cache_hit/miss,rails_ai_bridge.auth.success/failure, andrails_ai_bridge.rate_limit.hitevents. - Rails 8.1+ introspection signals (#73/#86) —
GemRegistrynow recognizesmission_control-jobs;ConfigIntrospectorreportsqueue_adapterandcable_adapter;AuthIntrospectorsurfaces Rails 8 generator patterns (authentication_concern,generates_token_for,normalizes).
Changed
- Summary-first defaults (#70/#87) —
rails_get_schemaandrails_get_model_detailsnow default todetail: 'summary'when listing, reducing the chance of oversized tool responses. Callers can still opt intostandardorfulland use filters for specific tables/models.
Tests
- Total: 2157 examples, 0 failures, 94.34% line coverage.
[3.5.1]
Security
- Harden
DefaultGitRunnergit commands against option injection by validating clone URL/destination and using--separators forgit clone; addnosemgrepsuppressions for documented false positives ingit pullandgit checkout. - Add
protect_from_forgeryto all test/fixtureApplicationControllerclasses. - Replace
content_tagwithtag.h1in the internal testApplicationHelperand rename the misleadingrawvariable inConfig::Mcp. - Add
nosemgrepcomments with explanatory notes for unscoped-find false positives in internal test controllers. - Harden
rails_search_coderipgrep command with a--separator and replace shell-basedwhich rgdetection with directrg --versionchecks.
[3.5.0]
Added
git_timeoutfor git operations —Config::Registry#git_timeout(default30seconds) is now passed toDefaultGitRunner, which wraps every git subprocess (clone,pull,checkout) inTimeout.timeout. A slow or unreachable remote can no longer block the calling thread indefinitely; a descriptiveRuntimeError(e.g."git clone timed out after 30s") is raised instead.DefaultGitRunner#timeoutexposes the configured value for introspection.git_pull_ttl— per-pack pull freshness window —Config::Registry#git_pull_ttl(default86400seconds = 24 h) controls how oftenSkillSourceResolverissues agit pullfor an already-cached pack. Successiveresolvecalls within the TTL window skip the pull entirely, removing the previous behaviour of pulling on every resolver rebuild. Set to0to restore pull-on-every-resolve. Pull timestamps are tracked in a thread-safe, in-memoryMutex-guarded hash; they reset when the process restarts.checkout_reftimeout —git checkout <ref>is now also subject togit_timeout. ASkillSourceResolver::ResolutionErroris raised on timeout with the ref name and pack source in the message.Registry::Truncatableshared module (lib/rails_ai_bridge/registry/truncatable.rb) — extracts thetruncate(text, max)helper that was duplicated betweenRakePresenterandRegistryCatalogFormatter. Both classes nowinclude Truncatableand the private duplicates are removed.Engine.to_preparehook — the Rails Engine now registers aconfig.to_prepareblock that callsRegistry.invalidate_resolver_cache!. This discards the cached resolver on every Zeitwerk code reload in development, preventing stale config after an initializer change. In production it fires once after eager load and is effectively a no-op.depends_onmissing-dependency warning —PackResolvernow emits a clear[rails-ai-bridge]warning to stderr when an active pack declaresdepends_onentries that are not in the active pack set. The warning names each missing dependency and tells the user which manifest field to update. Packs still load; this is an advisory warning, not an abort. Transitive dependency loading remains unimplemented (seedocs/gem-general-improvements.md).- Stable local pack names — local registry packs previously received names like
local_0,local_1based on array index, so reorderinglocal_registry_pathssilently shifted pack identities. Names are now derived from a SHA256 digest of the path (local_<first 8 hex chars>), making them stable regardless of ordering. docs/offline-mode.md— design plan for a futureoffline:config flag that prevents all git operations and serves the local cache as-is; includes rake pull task design, vendored snapshot pattern, and CI caching guidance.docs/gem-general-improvements.md— roadmap of eight broader improvements: manifest schema validation, pack version lock file, agent-facing JSON output from rake tasks, full SHA-256 cache keys, transitivedepends_onloading, structured logging, and more.
Changed
PackResolvererrors raised asResolutionError— the two bareraise "..."calls inPackResolver(unknown pack name, missing tile manifest) and the one inload_local_registriesnow raiseSkillSourceResolver::ResolutionErrorinstead of a plainRuntimeError. Callers that rescueResolutionErrorfromSkillSourceResolverwill now also catch pack-level failures without needing a separaterescue RuntimeError.SourceParserrejectshttp://URLs — plain HTTP was previously accepted as a git source. It is now rejected because cloning over unencrypted HTTP exposes credentials and pack content in transit. Usehttps://orgit@(SSH) instead. The error message and module docstring are updated to explain the reason and list the supported formats.ListRegistrytype-guard comment — theunless %w[skills agents packs].include?(type)guard is retained as a defence-in-depth fallback (the MCP SDK enum constraint catches invalid values first) and now carries an explanatory comment to prevent future confusion.Registry.build_resolver_uncached— wiresgit_timeoutandgit_pull_ttlfromConfig::RegistryintoDefaultGitRunnerandSkillSourceResolverrespectively, so configuration changes take effect on the next resolver rebuild.
Fixed
validate_cache_dirdocumentation clarified — the YARD docstring now explains why the lexicalPathname#cleanpathcheck (rather thanFile.realpath) is used: the cache directory may not exist yet at validation time. The security guarantee is stated explicitly: cache keys are SHA256-derived and not attacker-controlled, so even an unexpected symlink target is safe.
Tests
-
checkout_ref— 8 new examples covering: successful checkout returns the cache path; git checkout called with the correct ref; non-zero exit raisesResolutionError; error message includes ref name, source pack name, and stderr text; timeout raisesResolutionErrorwith"timed out"and ref name in message; nil ref skipsgit checkoutentirely. -
Pull freshness — 3 new examples: TTL=0 always pulls on every resolve; large TTL skips the second pull within the window; second resolve after TTL expiry re-pulls (verified by backdating
@last_pulledvia instance variable access). -
DefaultGitRunnertimeout — 4 new examples:#timeoutdefaults to 30; configurable via constructor; clone timeout raisesRuntimeErrorwith duration; pull timeout same. -
ResolverCacheTTL spec — replacedsleep(0.01)(wall-clock dependency) with an injectablemonotonic_clock:lambda that returns0on the first call and99_999thereafter, making the TTL-expiry test deterministic and instant. -
Total: 2043 examples, 0 failures, 94.67% line coverage (up from 94.53%)
-
Registry data structures (PR 1) — new
RailsAiBridge::Registrymodule with immutable value objects porting the Rustagent-mcp-runtimeregistry types to Ruby:Registry::RegistryManifest— root manifest (version, packs, default_stack);from_json/from_fileRegistry::PackDefinition— single pack descriptor (source, tile, always_loaded, depends_on)Registry::TileManifest— pack skill/agent catalog;from_json/from_fileRegistry::SkillEntry,Registry::AgentEntry— metadata entries for skills and agentsRegistry::DeprecatedEntry— deprecation redirect (moved_to, message, removed_in)Registry::FrontmatterParser— internal YAML frontmatter extractor for skill markdown files; used when aSkillEntrycarries no description intile.json
-
Git source resolver + pack detector (PR 2) — git repository caching and framework auto-detection:
Registry::GitRunner— module interface for git operations (injectable for tests)Registry::DefaultGitRunner— Open3-based implementation using stdlib git commandsRegistry::SkillSourceResolver— resolves remote git sources to local cache directories; clones if missing, pulls if cached; cache dir defaults to~/.rails-ai-bridge/cache/(env override:RAILS_AI_BRIDGE_CACHE_DIR); cache key uses sanitized source + SHA256 hashRegistry::DetectedFramework— enum-like value object (Rails, Hanami)Registry::PackDetector— detects Rails/Hanami frameworks from Gemfile content; supports single/double quotes, version constraints, ignores commented lines
-
Pack resolver + registry resolver (PR 3) — priority-based pack loading and skill/agent resolution:
Registry::PackResolver— service object that resolves and loads skill packs from the registry manifest; handles always_loaded packs, explicit pack selection, framework auto-detection, and local registry overrides; returns aRegistry::Resolverwith all packs loaded and prioritizedRegistry::Resolver— core resolver that aggregates active packs and resolves queries; provides priority-based resolution of skills and agents, handles deprecation redirects, validates dependencies, and guards against path traversal attacksRegistry::LoadedPack— value object representing a loaded pack (name, tile, base_path, priority)Registry::ResolvedSkill— value object representing a resolved skill/agent (name, pack, path, content)Registry::SkillSummary— value object for skill/agent catalogs (name, pack, description)- Priority assignment: local=0, rails/hanami=10, core=20, other=30 (lower is higher priority)
- Path traversal guard using canonical path comparison to prevent directory escape attacks
- Dependency validation with warnings for unsatisfied pack dependencies
-
Registry configuration (PR 4) — configuration object for registry resolution:
Config::Registry— configuration sub-object for registry resolution settingsregistry.registry_manifest_path— path to registry manifest JSON (default:config/rails_ai_bridge_registry.json)registry.skill_cache_dir— directory for caching git repositories (default:~/.rails-ai-bridge/cache)registry.skill_packs— explicit pack names to load, ornilfor auto-detection based on frameworkregistry.local_registry_paths— local registry directory paths for skill pack overrides- Registry module required in main
rails_ai_bridge.rbfor configuration availability
-
Registry tools, cache, source formats, and docs (PR 5 → PR 6) — user-visible entry points plus three production-quality refinements:
Tools::ListRegistry(rails_list_registry) — single MCP tool replacing the previousrails_list_skills,rails_list_agents, andrails_list_packs; requiredtype:param ("skills"|"agents"|"packs"); optionalpack:filter for skills/agents; innerRegistryCatalogFormatterclass owns all markdown rendering (SRP)Registry::ResolverCache— thread-safe in-memory cache for the wiredResolver; configurable TTL viaconfig.registry.resolver_ttl(default 1800 s = 30 min); nil results never cached so manifest-missing setup retries on next call;Registry.invalidate_resolver_cache!for explicit invalidationConfig::Registry#resolver_ttl— new accessor with 1800 s defaultRegistry::SourceParser— new single-responsibility parser that classifies source strings into:local_path,:git_url, or:github_shorthandand resolves canonical URLs; raisesResolutionErrornaming all three valid formats for invalid inputs;SkillSourceResolver#resolvenow delegates toSourceParserand returns local paths directly without git operationsPackDefinition#ref— new optional field for git version pinning (branch, tag, or SHA);SkillSourceResolverrunsgit checkout refafter clone/pull when setPackResolver— default pack catalog filename changed fromtile.jsontodirectory.json; priority matching is now case-insensitiveRegistry::RakePresenter— extracted from inline rake task logic; owns all CLI formatting for skill tables and resolve outputrails ai:skills:list— delegates toRakePresenterrails "ai:skills:resolve[pack,skill_name]"— delegates toRakePresenterrails ai:skills:clear_cache— new rake task; removes cached pack repositories and invalidates the in-memory resolver cachedocs/skill-registry-guide.md— new user guide covering concepts, quick start, source formats, priority rules, version pinning,directory.jsonformat, MCP tool reference, rake task reference, resolver cache, troubleshooting, and security modeldocs/registry-resolution.md— updated to "Registry Resolution Reference"; alltile.jsonreferences updated todirectory.json; new source formats table; newreffield;resolver_ttlconfig option; cache management section; security section updated forSourceParser
[3.4.0] - 2026-05-21
Added
TimedRunner— per-introspector wall-clock timing (#36) — newRailsAiBridge::Introspector::TimedRunner.call(klass, app)value object wraps any introspector class and returns{ result:, duration_ms: }. UsesProcess.clock_gettime(CLOCK_MONOTONIC)for accurate measurement regardless of system clock adjustments. Duration is recorded even when the introspector raises, so you can diagnose slow-then-failing classes. Sequential runs now log duration atdebuglevel viaRails.logger.debug.- Config-driven
ParallelRunnerpool size (#36) —config.parallel_pool_size(default4) sets the upper bound for theConcurrent::FixedThreadPool; the actual size ismin(introspector_count, pool_size)so no idle threads are ever created. - Per-future timeout for parallel introspection (#36) —
config.parallel_timeout_seconds(default10) is enforced on eachConcurrent::Futureviafuture.value(timeout). Introspectors that exceed their budget are cancelled and return{ error: "timed out after Ns" }without blocking the rest of the pool. The pool'swait_for_terminationalso uses this value. - Rubydex incremental indexing (#38) — new
RailsAiBridge::RubydexAdapter::IncrementalIndexerservice skips unchanged files on re-index using mtime tracking (integer seconds, no IEEE 754 precision loss). A full rebuild is triggered when the ratio of changed files exceedsconfig.rubydex_incremental_threshold(default0.3). The mtime snapshot can optionally survive process restarts viaconfig.rubydex_persist_index(defaultfalse). config.rubydex_incremental_threshold(#38) (default0.3) — ratio of changed-to-total files above which the incremental indexer falls back to a full rebuild.config.rubydex_persist_index(#38) (defaultfalse) — whentrue, the rubydex mtime snapshot is written to disk alongside the index so incremental re-indexing survives process restarts.- Path-traversal guard for rubydex index path (#38) —
RubydexAdapter#indexer_optionsnow sanitisesconfig.rubydex_index_paththrough aPathname#cleanpath+ root-prefix check, returningnil(and falling back to the default) for any path that escapesRails.root. - Bridge file freshness stamps (#37) — generated bridge files (CLAUDE.md, AGENTS.md, GEMINI.md, .cursorrules, etc.) now embed a freshness header containing the generation timestamp, a 12-character source fingerprint (SHA-256 of
db/schema.rb+config/routes.rb), and the gem version. Files are skipped on re-generation when their fingerprint matches, eliminating unnecessary timestamps and noisy git diffs. Fingerprinter.source_fingerprint(#37) — new singleton method that hashes the app's schema and routes files into a compact 12-char hex fingerprint used by the freshness system.
Fixed (Security & Architecture Audit)
- ReDoS Vulnerability in
RubySearch— Added a 2-second timeout to theRegexp.newengine to prevent catastrophic backtracking denial-of-service on malicious search patterns. - Path Traversal via Symlinks in
RubydexAdapter—sanitize_index_pathnow usesPathname#realpathto strictly validate that the configured index path resolves safely inside theRails.rootboundary. - TOCTOU Race Condition in
IncrementalIndexer— Upgraded mtime tracking from integer seconds (to_i) to rational (to_r) for precise sub-second caching, preventing scenarios where high-frequency file modifications within the same second bypassed change detection. - Threshold Edge Case in
IncrementalIndexer— Changed the rebuild cutoff comparison from>to>=so that precise boundary thresholds (like 100% of files) trigger full rebuilds correctly. - Memory Leaks & Exhaustion in
ParallelRunner— Replaced deprecatedclear_active_connections!withconnection_pool.release_connection, and explicitly addedpool.killto forcefully shut down long-running threads on timeouts. - State Leakage in Extractors — Refactored
FilterExtractor,AssociationExtractor, andSourceMacroExtractorto eliminate shared mutable state, establishing purely functional object APIs and tightening private encapsulation. db/structure.sqlfallback (#37) —source_fingerprintautomatically falls back todb/structure.sqlwhendb/schema.rbis absent (apps using SQL schema format are now supported).FreshnessHeadermodule (#37) — centralized utility for embedding and extracting freshness metadata from bridge files. Supports both Markdown (HTML comment header) and JSON (_metaobject) formats, with backward-compatible parsing of older files that lack the gem-version field.- Bridge freshness Doctor check (#37) — a new
BridgeFreshnessCheckeris registered with theDoctorservice. It reports stale bridge files (fingerprint mismatch) or missing bridge files as:warn, and fresh files as:pass. The Doctor now runs 16 total checks. rails ai:checkrake task (#37) — runs all diagnostic checks and exits with code1if any check fails, enabling straightforward CI/CD integration (e.g.,rails ai:check || exit 1).CHECK=1pre-generation guard (#37) — passCHECK=1torails ai:bridge(or any bridge sub-task) to run Doctor diagnostics first; generation is aborted if any check fails.RailsAiBridge::RakeHelpersmodule (#37) — extracted top-level rake helper methods (print_result,apply_context_mode_override,conflict_strategy,run_pre_generation_checks) from globalObjectscope into a properly namespaced module.CacheWarmer&CachedSnapshot(#36) — implemented TTL-based thread-safe caching system withconfig.cache_warm_on_bootto preemptively load context into memory on application start.
Changed
rubydexenabled by default — Therubydexgem (v0.2.3) is now a mandatory dependency and semantic analysis is enabled out of the box (@rubydex_enabled = true). This provides zero-config code graph and semantic context functionality to all users.- Improved IDE configurations in documentation — Promoted HTTP/SSE as the primary and highly recommended connection method for
rbenv/rvmusers within IDEs (like Antigravity and Cursor) to bypass subprocess ruby environment pathing issues. Introspector#run_single(#36) — sequential execution is now routed throughTimedRunnerinstead of a barerescueblock. Error handling behaviour is unchanged ({ error: message }), but every introspector call now produces a debug-level duration log entry.ParallelRunner#resolve_future(#36) — usesfuture.value(timeout)+future.complete?check instead of blockingfuture.value!. Anilreturn from a timed-out future is no longer misinterpreted as a successful result.ParallelRunnerpool shutdown (#36) —wait_for_terminationnow usesconfig.parallel_timeout_secondsinstead of a hardcoded10.RubydexAdapter#handle_index_result(#38) — on:reindex!failure, existing@graphand@indexedstate is preserved rather than reset tonil/false, preventing a full context blackout on transient indexing errors.- Integer mtimes throughout
IncrementalIndexer(#38) —serialize_mtimes,deserialize_mtimes, andfile_mtimenow all operate in integer seconds (Time#to_i) to avoid IEEE 754 floating-point comparison drift. FreshnessHeader(#37) — expanded API withembed_for(fmt, ...),extract_metadata_for(fmt, content), andextract_fingerprint_for(fmt, content)dispatching methods. JSON and Markdown branching is now fully centralized here, removing format-awareif fmt == :jsonconditionals from callers.ContextFileSerializer(#37) — refactored to use a newFreshnessWriterinner class that encapsulates freshness metadata embedding and file write decisions. This eliminatesControlParameter,UtilityFunction, andLongParameterListReek warnings.BridgeFreshnessChecker(#37) — refactored with aScanResultstruct to eliminate the 6-parametercheck_filemethod; introducedscan_files,accumulate_file_result,stale?, andfreshness_checkhelpers reducingTooManyStatementsandDuplicateMethodCallReek warnings.Fingerprinter.source_fingerprint(#37) — extractedschema_path(root)andread_source_content(paths)private helpers to reduce method statement count.RubySearch(#35) — wrapped the 5 search params into aSearchParamsstruct to resolve theTooManyInstanceVariablesReek warning; extractedsecret_file?(basename)fromskip_file?to fixFeatureEnvy; addedSECRET_EXTENSIONSconstant.RipgrepSearch::CommandBuilder(#35) — moved hardcoded secret file globs to aSECRET_EXCLUDESconstant; renamed helpers toexcluded_path_flags/secret_exclude_flags; added# :reek:UtilityFunctionsuppressions for intentional stateless helpers.Validator(#35) — extractedeffective_max_bytes,present?,normalize_extension,safe_extension?,build_search_path,within_root?,path_not_found, andpattern_too_long_errorhelpers. FixesDuplicateMethodCallonBaseTool.text_response("Path not found: ...")invalidate_path_security.SourceMacroExtractor(#35) — splitadd_attachment_macrosinto three single-step helpers (add_single_attached,add_many_attached,add_rich_text) to reduce statement counts.- Rake namespace splitting (#35) —
namespace :aireopened across multiple smaller blocks inrails_ai_bridge.raketo comply withMetrics/BlockLengthRuboCop limit.
Fixed
ASSISTANT_TABLEconstant redefinition warning (#35) — wrapped constant definition inunless defined?to prevent warnings when Rake tasks are loaded multiple times in test environments.
Tests
- Added 68 new examples covering:
TimedRunner— result forwarding, error capture, monotonic duration, error-path durationParallelRunner— config-driven pool size, per-future timeout, pool shutdown, mixed success/failure,available?with pool-size and missing-constant edge casesIntrospector— sequentialTimedRunnerwiring (plain result, noduration_msenvelope), error capture in sequential mode, debug log assertionAppOverviewFormatter— nil/error guards, optional fields, field orderingGemsFormatter— nil/error guards, total count, Notable Gems section, category+name sort orderMigrationsFormatter— nil/error guards, schema version, pending migrations count, recent migrations with and without actionsRubySearch/FileProcessor— pattern matching, max_results cap, secret file skipping (.env,.key,.pem,.p12,.pfx,.crt), excluded paths, file_type filtering, case-insensitive search, relative paths, unreadable file recovery,:fullreturn signalFingerprinter— restored.computeand.changed?unit tests; addeddb/structure.sqlfallback and schema.rb-wins-when-both-exist edge casesFreshnessHeader— backward-compatible parsing of headers without gem version
- Total: 1,745 examples, 0 failures, 94.49% line coverage (up from 94.04%)
[3.2.0] - 2026-05-04
Added
- Recursive symlink protection —
FileManagementServicenow recursively resolves and validates every directory component of a path. This prevents directory-traversal escapes via symlinks in non-existent nested paths (e.g., writing tounsafe_link/new_dir/file.txt). - ActiveRecord-free resilience —
NonArModelsIntrospectornow safely handles Rails stacks without ActiveRecord (e.g., pure API or alternative ORMs) by guardingActiveRecord::Baseinheritance checks. - Robust Rails logger guards — all diagnostic and error logging now uses
defined?(Rails.logger)to preventNoMethodErrorin environments whereRailsis defined but lacks a logger.
Changed
- Terminology alignment — Updated generated documentation and command descriptions from "context" to "bridge" (e.g.,
rails ai:watchnow describes "Auto-regenerate bridge files"). - ConventionDetector stability —restored standard error-hash return
{ error: msg }forConventionDetector#callto comply with introspector standards, while maintaining explicitRails.logger.warnfor observability.
Fixed
- Rake task spec cleanup — removed unused
let(:task_path)and fixed duplication in rake task loading. - Install generator optimization — removed redundant double-introspection call during the install process.
[3.1.1] - 2026-05-03
Changed
- Small Security Improvement — There was an update from rubygems security, so this made a new release needed, no new functionality added
[3.1.0] - 2026-05-01
Added
- Task-relevance ordering for compact context — model lists now rank by semantic tier, structural complexity, route density, recent migrations, and optional database-size signals instead of relying mostly on alphabetical order.
- Endpoint focus summaries — compact stack/project context now surfaces the busiest route
targets with direct
rails_get_routes(controller:"...", detail:"summary")drill-down hints. - Database size buckets — the optional
database_statsintrospector now annotates PostgreSQL approximate row counts assmall,medium,large, orhot; generated context shows these hints only whendatabase_statsis explicitly enabled. - Context quality matrix specs — generated-output acceptance coverage now exercises standard CRUD, large-schema, API-only, Hotwire, engine-style, and regulated/no-domain-metadata profiles, with real Rails-shaped fixture trees for API-only, Hotwire, large-schema, engine-style, and regulated/no-domain-metadata apps plus bounded output and secret-adjacent regression checks.
- Serialization benchmark guard — large-fixture compact serialization now has a small performance budget to catch accidental context bloat.
- MCP large-payload stability checks — route/schema tool specs now exercise truncation, pagination, next-offset guidance, and section-cache reuse against large payloads.
Changed
- Claude rules —
.claude/rules/rails-context.mdnow includes bounded endpoint focus and route drill-down guidance;.claude/rules/rails-schema.mdadds optional size-bucket hints. - Route MCP pagination —
rails_get_routesstandard/full output now includes a nextoffsethint when more route rows are available. - Secret-bearing config paths — generated context,
rails_get_conventions, and therails://conventionsMCP resource now omit dotenv files, Rails credentials files, secret/private directories, master keys, and private key material from config-file listings while preserving safe operational files such asconfig/database.yml. - Convention detection with custom Rails paths — architecture and directory-structure signals
now honor configured Rails paths for directories such as
app/modelsandapp/serviceswhile keeping generated output on logical names instead of absolute local paths. - Model introspection with custom Rails paths — ActiveRecord source-derived metadata and
non_ar_modelsdiscovery now resolve every configuredapp/modelspath, so apps that place domain models outside the conventional directory still generate useful model context. - Controller and frontend introspection with custom Rails paths — controller source metadata,
view summaries, Stimulus controllers, and Turbo frame/stream/broadcast detection now honor
configured
app/controllers,app/views,app/helpers,app/components, andapp/javascript/controllerspaths where Rails exposes them. - View detail access with custom Rails paths —
rails_get_view(path:"...")andrails://views/{path}now resolve files through configuredapp/viewspaths while preserving traversal protection. - Specialized introspectors with custom Rails paths — Active Storage, Action Text,
CurrentAttributes, API serializers/GraphQL/versioning/rate-limit scans, Devise,
has_secure_password, Rails auth, Pundit, and CanCanCan detection now honor configured logical Rails paths instead of assuming only conventionalapp/*directories. - Copilot, Codex, Cursor, Windsurf, and shared compact serializers — key model sections now use the same relevance score so assistants see core, routed, recently changed, or hot-domain models before lower-signal supporting models.
- Generated override guidance — compact instructions no longer include the literal
omit-merge marker string unless reading the actual override stub; user-facing docs still explain
how to activate
config/rails_ai_bridge/overrides.md.
[3.0.0] - 2026-04-28
Added
- Interactive install generator —
rails generate rails_ai_bridge:installnow prompts for an install profile:custom(per-format prompts),minimal(thin shims, no split-rule dirs),full(all formats + split-rule dirs), ormcp(only.mcp.json, generate files later). Pass--profile=<name>to skip the prompt, or--skip-contextto defer all file generation (useful in CI/CD pipelines). split_rules:parameter ongenerate_context—RailsAiBridge.generate_contextandContextFileSerializernow acceptsplit_rules: falseto skip generating per-assistant rule directories (.claude/rules/,.cursor/rules/, etc.). Used by theminimalprofile to avoid creating directories that aren't needed for simple shim installs.-
on_conflict:option ongenerate_contextandContextFileSerializer— controls what happens when a generated file already exists with different content.:overwrite(default) — silently replaces the file (no behaviour change for existing users):skip— keeps the existing file unchanged:prompt— asks interactively via stdin before overwritingProc— caller supplies(filepath) -> bool; returntrueto overwrite Rake tasks expose this viaCONFIRM=1 rails ai:bridge(enables:promptfor all bridge tasks).
config.watcher_formats— limits which formatsrails ai:watchregenerates on file change. Defaults to:all. Set to e.g.%i[claude cursor]to avoid regenerating formats you don't use during active development.
Changed
RailsAiBridge.generate_contextsignature — keyword parameters (format:,split_rules:,on_conflict:) are now forwarded via**options(two formal parameters instead of four). All existing call sites using keyword arguments are unaffected.Providers::Factorystrategy pattern —ContextFileSerializernow dispatches serializers and split-rule generators through a registry factory (REGISTRY+SPLIT_REGISTRY) instead of hardcodedcase/ifchains, making it trivial to add new output formats.ProfileResolverextraction — install profile resolution logic extracted fromInstallGeneratorinto a dedicatedGenerators::InstallGenerator::ProfileResolverclass, with Thor shell injected viashell:so existing tests remain intact.GemRegistryextraction —NOTABLE_GEMSconstant and categorization logic extracted fromGemIntrospectorintoIntrospectors::GemRegistry, eliminating a duplicatedetect_notable_gemscall in the introspection pipeline.
Removed
exe/rails-ai-bridgestandalone CLI — therails-ai-bridge serve / bridge / inspectbinary has been removed. All commands are available as rake tasks (rails ai:serve,rails ai:bridge,rails ai:inspect, etc.) which are the recommended interface.
[2.2.0] - 2026-04-04
Added
non_ar_modelsintrospector — Lists Ruby classes underapp/modelsthat are not ActiveRecord models, tagged[POJO/Service]in MCP listings and.claude/rules/rails-models.md. Context key::non_ar_modelswith{ non_ar_models: [{ name, relative_path, tag }] }. Not in:standardor:fullpresets (opt in viaconfig.introspectors << :non_ar_models). Included in thedomain_metadatadisable category when enabled.- Model semantic classification — Each ActiveRecord model in introspection
output now includes
semantic_tier(core_entity,pure_join,rich_join,supporting) andsemantic_tier_reasonfor MCP transparency. Join tables used inhas_many :throughare detected; payload columns beyond FKs and metadata yieldrich_join. config.core_models— List model class names to tag ascore_entityfor AI-focused context (initializer comment +Config::Introspection).RailsAiBridge::ModelSemanticClassifier— PORO that computes tiers from columns,belongs_toforeign keys, and through-association membership..claude/rules/rails-context.md— Semantic layer summary (app metadata + models grouped by tier) for Claude Code, alongside existing split rules.
Changed
rails-context.mdtier lists — In compactcontext_mode, at most 20 model names persemantic_tierwith an overflow line referencingrails_get_model_details(detail:"summary"); full mode lists all names per tier.- Claude rules
rails-models.md— Each model line includestier: …when present. rails_get_model_detailsformatters — Summary, standard, full, and single-model views include semantic tier where applicable.- Combustion test setup —
Combustion.pathis set tospec/internal,Combustion::Database.setupruns after boot so:memory:SQLite has schema before examples, and the internalExampleJobno longer subclassesActiveJob::Base(Active Job is not loaded in the minimal stack).
[2.1.0] - 2026-04-02
Added
- Gemini Support: Added support for Google's Gemini AI assistant via
GEMINI.md. - New Rake Task: Added
rails ai:bridge:geminito generate Gemini-specific context. - Context Harmonization: Refactored all provider serializers (Claude, Gemini, Codex,
Copilot, Cursor, Windsurf) to use a shared
BaseProviderSerializer. - Enhanced AI Guidance: All context files now feature directive headers, complexity-sorted model lists, and explicit behavioral rules to improve AI code generation.
- Improved Metadata: Context files now include descriptions for key config
files and standard maintenance commands (e.g.,
rubocop).
Changed
- Internal Refactor: Extracted common rendering logic into
RailsAiBridge::Serializers::Providers::BaseProviderSerializerto ensure consistency and maintainability across all AI assistants.
[2.0.0] - 2026-03-31
Added
- Shared runtime context provider — MCP tools and
rails://...resources now read throughRailsAiBridge::ContextProvider, keeping cache invalidation and snapshot semantics aligned across both entry points. - Explicit extension registries —
config.additional_introspectors,config.additional_tools, andconfig.additional_resourcesallow host apps or companion gems to extend the built-ins without patching core constants. - HTTP transport Rack builder —
RailsAiBridge::HttpTransportAppcentralizes HTTP MCP request handling for both standalone server mode and middleware auto-mount. - Section-level context reads —
ContextProvider.fetch_sectionandBaseTool.cached_sectionlet single-section tools avoid rebuilding or materializing the full snapshot path when unnecessary. - Folder-level contributor docs — key runtime folders now include local
README.mdguides for structure, boundaries, and extension points. - Extensibility integration coverage — specs now prove that a custom introspector, tool, and resource can be registered and used together from the host app configuration surface.
- Serializer formatter objects —
MarkdownSerializeris now a thin orchestrator delegating to 37 single-responsibilityFormatters::*classes; each formatter is independently testable and injectable. - Tool response formatters —
GetSchemaandGetModelDetailsdelegate all rendering toTools::Schema::*andTools::ModelDetails::*formatter classes; toolcallmethods are ≤20 lines each. Config::Auth,Config::Server,Config::Introspection,Config::Output—Configurationis now aForwardablefacade over four focused sub-objects; each is independently readable and injectable.Mcp::Authenticator— consolidates strategy resolution, static-token lookup, and configuration predicates into a single entry point, replacing the previous split betweenMcpHttpAuthandMcp::HttpAuth.Mcp::HttpRateLimiter— optional in-process sliding-window rate limiter per client IP; configured viaconfig.mcp.rate_limit_max_requestsandconfig.mcp.rate_limit_window_seconds. Returns 429 withRetry-Afterheader when exceeded.Mcp::HttpStructuredLog— optional one-JSON-line-per-request logger for the MCP HTTP path; enabled viaconfig.mcp.http_log_json = true. Logsevent,http_status,path,client_ip, andrequest_id; never logs tokens or full Rack env.Config::Mcp— newconfig.mcpsub-object (5th façade sub-config) for MCP HTTP operational settings:mode,security_profile,rate_limit_max_requests,rate_limit_window_seconds,http_log_json,authorize,require_auth_in_production.config.mcp.authorize— optional post-auth lambda(context, request) { truthy }; returning falsey yields HTTP 403 on the MCP path.config.mcp.require_auth_in_production— whentrue, boot fails in production unless an auth mechanism is configured.HttpTransportAppupdated — request pipeline is now: path check → auth → authorize → rate limit → structured log → transport.SectionFormattertemplate method base — 22 of 37 formatters now inherit fromSectionFormatter, which handles the nil/error guard in one place; each formatter only implementsrender(data).Serializers::Providersnamespace — 10 LLM provider serializers extracted intolib/rails_ai_bridge/serializers/providers/, separating provider concerns from domain infrastructure (MarkdownSerializer,JsonSerializer, formatters).UPGRADING.md— new upgrade guide documentingconfig.mcpsettings, rate limit semantics, structured logging,authorizebehaviour, and therequire_auth_in_productionflag.- Contributor roadmaps —
docs/roadmaps.md,docs/roadmap-mcp-v2.md,docs/roadmap-context-assistants.mdadded.
Changed
- Install generator messages — the install flow now reports created vs unchanged files correctly and the generated initializer comments reflect the current preset sizes.
- Fingerprint reuse on invalidation — context refresh reuses a single fingerprint snapshot per fetch cycle instead of scanning twice when cached context becomes stale.
FullClaudeSerializer,FullRulesSerializer,FullCopilotSerializer,FullCodexSerializerremoved — full-mode rendering is now handled by injecting header/footer formatter classes intoMarkdownSerializervia constructor arguments; no subclassing needed.- Test suite expanded to 841 examples at ≥87% line coverage.
Fixed
- Install generator output bug —
generate_contextresults are no longer iterated as raw hash pairs during install-time file generation. StandardFormatterpagination hint — navigation hint now correctly usesoffset + limit < total(consistent withSummaryFormatterandFullFormatter), preventing a spurious hint on the last page.
Upgrading from 1.x
No configuration changes required. Every config.* attribute from 1.x is still available unchanged —
Configuration now delegates to focused sub-objects (Config::Auth, Config::Server,
Config::Introspection, Config::Output, Config::Mcp) but exposes the same flat DSL.
The following internal classes were removed; they were never part of the documented public API:
| Removed | Replacement |
|---|---|
Mcp::HttpAuth / McpHttpAuth |
Mcp::Authenticator (same behaviour, single entry point) |
FullClaudeSerializer |
Pass header_class: Formatters::ClaudeHeaderFormatter to MarkdownSerializer |
FullCopilotSerializer |
Pass header_class: Formatters::CopilotHeaderFormatter to MarkdownSerializer |
FullCodexSerializer |
Pass header_class: Formatters::CodexHeaderFormatter to MarkdownSerializer |
FullRulesSerializer |
Pass header_class: Formatters::RulesHeaderFormatter to MarkdownSerializer |
If you were only using the gem through its initializer, rake tasks, or MCP server — no action needed.
[1.1.0] - 2026-03-20
Security
- HTTP MCP authentication — Optional Bearer token via
config.http_mcp_tokenorENV["RAILS_AI_BRIDGE_MCP_TOKEN"](ENV wins when set). When a token is configured,auto_mountandrails ai:serve_httprequireAuthorization: Bearer <token>. - Production guards —
config.auto_mount = truein production raises at boot unlessconfig.allow_auto_mount_in_production = trueand a non-empty MCP token is set.rails ai:serve_httpin production requires a token. rails_search_codeallowlist —file_typemust be an allowed extension (default:rb,erb,js,ts,jsx,tsx,yml,yaml,json). Extra extensions:config.search_code_allowed_file_types. Unrestricted search uses only those extensions; ripgrep/Ruby paths also exclude common secret filenames (e.g..env*,*.key,*.pem).- Credentials metadata —
credentials_keysis omitted from config introspection and therails://configMCP resource unlessconfig.expose_credentials_key_names = true.
[1.0.0] - 2026-03-18
Changed
- First release as
rails-ai-bridge— Ruby gem and GitHub project renamed fromrails-ai-context; public constant namespace isRailsAiBridge. Install withrails generate rails_ai_bridge:install. Host paths:config/initializers/rails_ai_bridge.rb,config/rails_ai_bridge/overrides.md,.mcp.jsonserver keyrails-ai-bridge, CLIexe/rails-ai-bridge. Breaking: no compatibility shim for the old gem name or paths.
Added
RailsAiBridge::Serializers::SharedAssistantGuidance— shared engineering rules, Rails performance pattern examples, optionalconfig/rails_ai_bridge/overrides.mdmerge into compact Copilot + Codex, and Cursorrails-engineering.mdcbody.- Cursor
rails-engineering.mdc—alwaysApply: trueengineering essentials + pointers to fullcopilot-instructions.md/AGENTS.mdand MCP rules. - Configuration —
assistant_overrides_path,copilot_compact_model_list_limit(default 5),codex_compact_model_list_limit(default 3);0lists no model names (MCP-only pointer). - Install generator — creates
config/rails_ai_bridge/overrides.mdstub andoverrides.md.examplewhen missing.
Fixed
- Overrides stub — install stub uses
<!-- rails-ai-bridge:omit-merge -->; overrides are not merged into Copilot/Codex until that line is removed. - Consistent controller counts in compact output — stack summaries use the controller introspector for the primary count (aligned with split rules); when routing lists more controller names than
app/controllersclasses, both counts are shown.
Changed
- Compact guidance —
CLAUDE.md, Copilot compact instructions, andAGENTS.mdinclude a performance/security baseline and note that generated files are snapshots;.codex/README.mddocuments re-merging team rules. - Copilot compact —
.github/copilot-instructions.mdleads with Engineering rules before stack inventory; MCP section notes path-scoped files under.github/instructions/and.cursor/rules/. - Copilot / Codex /
.cursorrulesorder — engineering rules → stack → optional repo-specific → performance + Rails patterns → trimmed models → MCP. - Legacy
.cursorrules— same ordering; model list usescopilot_compact_model_list_limit. rails-project.mdc— usesContextSummary.routes_stack_line; caps gem categories; referencesrails-engineering.mdc.
[0.8.0] - 2026-03-19
Added
- OpenAI Codex support via
AGENTS.md,.codex/README.md, andrails ai:context:codex. - Codex serializer integration in the context file pipeline so
format: :allnow includes Codex output.
Fixed
rails_search_codeinvalid regex handling — the Ruby fallback path now returns a controlled error response instead of raisingRegexpError.
Changed
- Fork metadata — gemspec,
server.json, README, CONTRIBUTING, SECURITY, and CODE_OF_CONDUCT now point to the maintained fork instead of upstream operational contacts. - Security documentation — clarified that MCP tools are read-only but may still expose sensitive application structure, especially over HTTP transport.
- Internal review summary — translated
resume.mdto English and updated it to reflect the current fork, Codex support, compatibility notes, and security posture.
[0.7.1] - 2026-03-19
Added
- Full MCP tool reference in all context files — every generated file (CLAUDE.md, .cursorrules, .windsurfrules, copilot-instructions.md) now includes complete tool documentation with parameters, detail levels, pagination examples, and usage workflow. Dedicated
rails-mcp-toolssplit rule files added for Claude, Cursor, Windsurf, and Copilot. - MCP Registry listing — published to the official MCP Registry as
io.github.crisnahine/rails-ai-contextvia mcpb package type.
Fixed
- Schema version parsing — versions with underscores (e.g.
2024_01_15_123456) were truncated to the first digit group. Now captures the full version string. - Documentation — updated README (detail levels, pagination, generated file tree, config options), SECURITY.md (supported versions), CONTRIBUTING.md (project structure), gemspec (post-install message), demo_script.sh (all 17 generated files).
[0.7.0] - 2026-03-19
Added
- Detail levels on MCP tools —
detail:"summary",detail:"standard"(default),detail:"full"onrails_get_schema,rails_get_routes,rails_get_model_details,rails_get_controllers. AI calls summary first, then drills down. Based on Anthropic's recommended MCP pattern. - Pagination —
limitandoffsetparameters on schema and routes tools for apps with hundreds of tables/routes. - Response size safety net — Configurable hard cap (
max_tool_response_chars, default 120K) on tool responses. Truncated responses include hints to use filters. - Compact CLAUDE.md — New
:compactcontext mode (default) generates ≤150 lines per Claude Code's official recommendation. Contains stack overview, key models, and MCP tool usage guide. - Full mode preserved —
config.context_mode = :fullretains the existing full-dump behavior. Also available viarails ai:context:fullorCONTEXT_MODE=full. .claude/rules/generation — Generates quick-reference files in.claude/rules/for schema and models. Auto-loaded by Claude Code alongside CLAUDE.md.- Cursor MDC rules — Generates
.cursor/rules/*.mdcfiles with YAML frontmatter (globs, alwaysApply). Project overview is always-on; model/controller rules auto-attach when working in matching directories. Legacy.cursorruleskept for backward compatibility. - Windsurf 6K compliance —
.windsurfrulesis now hard-capped at 5,800 characters (within Windsurf's 6,000 char limit). Generates.windsurf/rules/*.mdfor the new rules format. - Copilot path-specific instructions — Generates
.github/instructions/*.instructions.mdwithapplyTofrontmatter for model and controller contexts. Maincopilot-instructions.mdrespects compact mode (≤500 lines). rails ai:context:fulltask — Dedicated rake task for full context dump.- Configurable limits —
claude_max_lines(default: 150),max_tool_response_chars(default: 120K).
Changed
- Default
context_modeis now:compact(was implicitly:full). Existing behavior available viaconfig.context_mode = :full. - Tools default to
detail:"standard"which returns bounded results, not unlimited. - All tools return pagination hints when results are truncated.
.windsurfrulesnow uses dedicatedWindsurfSerializerinstead of sharingRulesSerializerwith Cursor.
[0.6.0] - 2026-03-18
Added
- Migrations introspector — Discovers migration files, pending migrations, recent history, schema version, and migration statistics. Works without DB connection.
- Seeds introspector — Analyzes db/seeds.rb structure, discovers seed files in db/seeds/, detects which models are seeded, and identifies patterns (Faker, environment conditionals, find_or_create_by).
- Middleware introspector — Discovers custom Rack middleware in app/middleware/, detects patterns (auth, rate limiting, tenant isolation, logging), and categorizes the full middleware stack.
- Engine introspector — Discovers mounted Rails engines from routes.rb with paths and descriptions for 23+ known engines (Sidekiq::Web, Flipper::UI, PgHero, ActiveAdmin, etc.).
- Multi-database introspector — Discovers multiple databases, replicas, sharding config, and model-specific
connects_todeclarations. Works with database.yml parsing fallback. - 2 new MCP resources —
rails://migrations,rails://engines - Migrations added to :standard preset — AI tools now see migration context by default
- Doctor check — New
check_migrationsdiagnostic - Fingerprinter — Now watches
db/migrate/,app/middleware/, andconfig/database.yml
Changed
- Default
:standardpreset expanded from 8 to 9 introspectors (added:migrations) - Default
:fullpreset expanded from 21 to 26 introspectors - Doctor checks expanded from 11 to 12
- Static MCP resources expanded from 7 to 9
[0.5.2] - 2026-03-18
Fixed
- MCP tool nil crash — All 9 MCP tools now handle missing introspector data gracefully instead of crashing with
NoMethodErrorwhen the introspector is not in the active preset (e.g.rails_get_configwith:standardpreset) - Zeitwerk dependency — Changed from open-ended
>= 2.6to pessimistic~> 2.6per RubyGems best practices - Documentation — Updated CONTRIBUTING.md, CHANGELOG.md, and CLAUDE.md to reflect Zeitwerk autoloading, introspector presets, and
.mcp.jsonauto-discovery changes
[0.5.0] - 2026-03-18
Added
- Introspector presets —
:standard(8 core introspectors, fast) and:full(all 21, thorough) viaconfig.preset = :standard .mcp.jsonauto-discovery — Install generator creates.mcp.jsonso Claude Code and Cursor auto-detect the MCP server with zero manual config- Zeitwerk autoloading — Replaced 47
require_relativecalls with Zeitwerk for faster boot and conventional file loading - Automated release workflow — GitHub Actions publishes to RubyGems via trusted publishing when a version tag is pushed
- Version consistency check — Release workflow verifies git tag matches
version.rbbefore publishing - Auto GitHub Release — Release notes extracted from CHANGELOG.md automatically
- Dependabot — Weekly automated dependency and GitHub Actions updates
- README demo GIF — Animated terminal recording showing install, doctor, and context generation
- SECURITY.md — Security policy with supported versions and reporting process
- CODE_OF_CONDUCT.md — Contributor Covenant v2.1
- GitHub repo topics — Added discoverability keywords (rails, mcp, ai, etc.)
Changed
- Default introspectors reduced from 21 to 8 (
:standardpreset) for faster boot; useconfig.preset = :fullfor all 21 - New files auto-loaded by Zeitwerk — no manual
require_relativeneeded when adding introspectors or tools
[0.4.0] - 2026-03-18
Added
- 14 new introspectors — Controllers, Views, Turbo/Hotwire, I18n, Config, Active Storage, Action Text, Auth, API, Tests, Rake Tasks, Asset Pipeline, DevOps, Action Mailbox
- 3 new MCP tools —
rails_get_controllers,rails_get_config,rails_get_test_info - 3 new MCP resources —
rails://controllers,rails://config,rails://tests - Model introspector enhancements — Extracts
has_secure_password,encrypts,normalizes,delegate,serialize,store,generates_token_for,has_one_attached,has_many_attached,has_rich_text,broadcasts_tovia source parsing - Stimulus introspector enhancements — Extracts
outletsandclassesfrom controllers - Gem introspector enhancements — 30+ new notable gems: monitoring (Sentry, Datadog, New Relic, Skylight), admin (ActiveAdmin, Administrate, Avo), pagination (Pagy, Kaminari), search (Ransack, pg_search, Searchkick), forms (SimpleForm), utilities (Faraday, Flipper, Bullet, Rack::Attack), and more
- Convention detector enhancements — Detects concerns, validators, policies, serializers, notifiers, Phlex, PWA, encrypted attributes, normalizations
- Markdown serializer sections — All 14 new introspector sections rendered in generated context files
- Doctor enhancements — 4 new checks: controllers, views, i18n, tests (11 total)
- Fingerprinter expansion — Watches
app/controllers,app/views,app/jobs,app/mailers,app/channels,app/javascript/controllers,config/initializers,lib/tasks; glob now covers.rb,.rake,.js,.ts,.erb,.haml,.slim,.yml
Fixed
- YAML parsing —
YAML.load_filecalls now passpermitted_classes: [Symbol], aliases: truefor Psych 4 (Ruby 3.1+) compatibility - Rake task parser — Fixed
@last_descinstance variable leaking between files; fixed namespace tracking with indent-based stack - Vite detection — Changed
File.exist?("vite.config")toDir.glob("vite.config.*")to match.js/.ts/.mjsextensions - Health check regex — Added word boundaries to avoid false positives on substrings (e.g. "groups" matching "up")
- Multi-attribute macros —
normalizes :email, :namenow captures all attributes, not just the first - Stimulus action regex — Requires
method(args) {pattern to avoid matching control flow keywords - Controller respond_to — Simplified format extraction to avoid nested
endkeyword issues - GetRoutes nil guard — Added
|| {}fallback forby_controllerto prevent crash on partial introspection data - GetSchema nil guard — Added
|| {}fallback forschema[:tables]to prevent crash on partial schema data - View layout discovery — Added
File.file?filter to exclude directories from layout listing - Fingerprinter glob — Changed from
**/*.rbto multi-extension glob to detect changes in.rake,.js,.ts,.erbfiles
Changed
- Default introspectors expanded from 7 to 21
- MCP tools expanded from 6 to 9
- Static MCP resources expanded from 4 to 7
- Doctor checks expanded from 7 to 11
- Test suite expanded from 149 to 247 examples with exact value assertions
[0.3.0] - 2026-03-18
Added
- Cache invalidation — TTL + file fingerprinting for MCP tool cache (replaces permanent
||=cache) - MCP Resources — Static resources (
rails://schema,rails://routes,rails://conventions,rails://gems) and resource template (rails://models/{name}) - Per-assistant serializers — Claude gets behavioral rules, Cursor/Windsurf get compact rules, Copilot gets task-oriented GFM
- Stimulus introspector — Extracts Stimulus controller targets, values, and actions from JS/TS files
- Database stats introspector — Opt-in PostgreSQL approximate row counts via
pg_stat_user_tables - Auto-mount HTTP middleware — Rack middleware for MCP endpoint when
config.auto_mount = true - Diff-aware regeneration — Context file generation skips unchanged files
rails ai:doctor— Diagnostic command with AI readiness score (0-100)rails ai:watch— File watcher that auto-regenerates context files on change (requireslistengem)
Fixed
- Shell injection in SearchCode — Replaced backtick execution with
Open3.capture2array form; added file_type validation, max_results cap, and path traversal protection - Scope extraction — Fixed broken
model.methods.grep(/^_scope_/)by parsing source files forscope :namedeclarations - Route introspector — Fixed
route.internal?compatibility with Rails 8.1
Changed
generate_contextnow returns{ written: [], skipped: [] }instead of flat array- Default introspectors now include
:stimulus
[0.2.0] - 2026-03-18
Added
- Named rake tasks (
ai:context:claude,ai:context:cursor, etc.) that work without quoting in zsh - AI assistant summary table printed after
ai:contextandai:inspect ENV["FORMAT"]fallback forai:context_fortask- Format validation in
ContextFileSerializer— unknown formats now raiseArgumentErrorwith valid options
Fixed
rails ai:context_for[claude]failing in zsh due to bracket glob interpretation- Double introspection in
ai:contextandai:context_fortasks (removed unusedRailsAiBridge.introspectcalls)
[0.1.0] - 2026-03-18
Added
- Initial release
- Schema introspection (live DB + static schema.rb fallback)
- Model introspection (associations, validations, scopes, enums, callbacks, concerns)
- Route introspection (HTTP verbs, paths, controller actions, API namespaces)
- Job introspection (ActiveJob, mailers, Action Cable channels)
- Gem analysis (40+ notable gems mapped to categories with explanations)
- Convention detection (architecture style, design patterns, directory structure)
- 6 MCP tools:
rails_get_schema,rails_get_routes,rails_get_model_details,rails_get_gems,rails_search_code,rails_get_conventions - Context file generation: CLAUDE.md, .cursorrules, .windsurfrules, .github/copilot-instructions.md, JSON
- Rails Engine with Railtie auto-setup
- Install generator (
rails generate rails_ai_bridge:install) - Rake tasks:
ai:context,ai:serve,ai:serve_http,ai:inspect - CLI executable:
rails-ai-bridge serve|context|inspect - Stdio + Streamable HTTP transport support via official mcp SDK
- CI matrix: Ruby 3.2/3.3/3.4 × Rails 7.1/7.2/8.0