rails-ai-bridge 4.0.0 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.mutant.yml +26 -0
  3. data/.reek.yml +4 -0
  4. data/.rubocop.yml +9 -0
  5. data/AGENTS.md +5 -5
  6. data/CHANGELOG.md +42 -1
  7. data/CLAUDE.md +5 -5
  8. data/CONTRIBUTING.md +2 -2
  9. data/GEMINI.md +1 -1
  10. data/README.md +14 -9
  11. data/Rakefile +2 -0
  12. data/SECURITY.md +4 -4
  13. data/docs/02-port-registry-resolution.md +152 -0
  14. data/docs/devin-setup.md +2 -2
  15. data/docs/mcp-security.md +53 -0
  16. data/docs/port-registry-resolution.md +1 -1
  17. data/docs/registry-resolution.md +5 -4
  18. data/docs/skill-registry-guide.md +77 -9
  19. data/lib/rails_ai_bridge/config/registry.rb +52 -4
  20. data/lib/rails_ai_bridge/context_provider.rb +1 -1
  21. data/lib/rails_ai_bridge/doctor/checkers/registry_checker.rb +135 -0
  22. data/lib/rails_ai_bridge/doctor.rb +2 -1
  23. data/lib/rails_ai_bridge/engine.rb +1 -0
  24. data/lib/rails_ai_bridge/instrumentation.rb +30 -1
  25. data/lib/rails_ai_bridge/introspectors/action_mailbox_introspector.rb +6 -0
  26. data/lib/rails_ai_bridge/introspectors/asset_pipeline_introspector.rb +7 -0
  27. data/lib/rails_ai_bridge/introspectors/database_stats_introspector.rb +8 -0
  28. data/lib/rails_ai_bridge/introspectors/devops_introspector.rb +7 -0
  29. data/lib/rails_ai_bridge/introspectors/i18n_introspector.rb +7 -0
  30. data/lib/rails_ai_bridge/introspectors/rake_task_introspector.rb +7 -0
  31. data/lib/rails_ai_bridge/introspectors/test_introspector.rb +8 -0
  32. data/lib/rails_ai_bridge/registry/context_provider_definition.rb +42 -0
  33. data/lib/rails_ai_bridge/registry/context_tool_spec.rb +53 -0
  34. data/lib/rails_ai_bridge/registry/pack_resolver.rb +101 -6
  35. data/lib/rails_ai_bridge/registry/rake_presenter.rb +32 -0
  36. data/lib/rails_ai_bridge/registry/registry_manifest.rb +137 -2
  37. data/lib/rails_ai_bridge/registry/skill_source_resolver.rb +69 -7
  38. data/lib/rails_ai_bridge/registry.rb +63 -1
  39. data/lib/rails_ai_bridge/resources.rb +87 -3
  40. data/lib/rails_ai_bridge/serializers/README.md +0 -1
  41. data/lib/rails_ai_bridge/serializers/json_serializer.rb +4 -0
  42. data/lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb +1 -1
  43. data/lib/rails_ai_bridge/server.rb +4 -1
  44. data/lib/rails_ai_bridge/tasks/rails_ai_bridge.rake +35 -4
  45. data/lib/rails_ai_bridge/tools/list_context_providers.rb +132 -0
  46. data/lib/rails_ai_bridge/tools/list_registry.rb +3 -3
  47. data/lib/rails_ai_bridge/tools/search_code.rb +31 -0
  48. data/lib/rails_ai_bridge/tools/usage_formatter.rb +72 -0
  49. data/lib/rails_ai_bridge/tools/use_agent.rb +54 -0
  50. data/lib/rails_ai_bridge/tools/use_skill.rb +57 -0
  51. data/lib/rails_ai_bridge/version.rb +1 -1
  52. data/lib/tasks/perf.rake +27 -0
  53. metadata +11 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a62e4a3003e8feb85f8ace7ec52c9ae89a2d0cd7c004673ca669cbacaf4fe665
4
- data.tar.gz: cf85e1034658180a1530dde70fa4b2c724b9ad289451f216b6723f40e94f4bb7
3
+ metadata.gz: 24c9dd6461240b9d6864b35c171c465635f9fdacc3c76195915f43b995a27f18
4
+ data.tar.gz: e97756c625478c854f78f661393d26043ba36b07b8941bed7a2a2c09b3a62a4b
5
5
  SHA512:
6
- metadata.gz: 95a1948e2f1ae02299f8b1505c83674f3172ea7da8fd384e17a9414c43ccee911a69e2f6713f320e8d520337c3cf8c343c082ad716ebb84d6128c64f4b2ceee9
7
- data.tar.gz: f4c81faedfe64c9268c635409d049c9a2b128306bcc666a55d0ef2f6624775bb098f10378d16d4819c6163d48cd8da42ebbf973474cb24183e09280a27e3548d
6
+ metadata.gz: f453227c44348be19356eecb728dac22328abcb20a99cf0430f441c68557346d93576527716764cae4f68f404fcab524dd44c4454b27a4f9078955632be8937f
7
+ data.tar.gz: 10e975098f252c37f37108e04d0e370b03f469829f9e2520334b180e83a8844a8276b9f4ed60ae650e0f9bd47dd7361b42885dcbdf87880e37d56c04152720fa
data/.mutant.yml ADDED
@@ -0,0 +1,26 @@
1
+ ---
2
+ # Mutant configuration for rails-ai-bridge critical paths.
3
+ #
4
+ # Run with: BUNDLE_GEMFILE=Gemfile-mutation bundle exec mutant run [subject expressions]
5
+ # Example: BUNDLE_GEMFILE=Gemfile-mutation bundle exec mutant run RailsAiBridge::Registry::FrontmatterParser
6
+ #
7
+ # The open-source usage mode is used because rails-ai-bridge is an
8
+ # open-source project. A commercial license is required for private
9
+ # repositories or advanced features (full operator set, isolation).
10
+ #
11
+ # Target: >80% mutation coverage on registry/tools.
12
+ #
13
+ # Subject expressions are passed on the CLI to target critical paths:
14
+ # RailsAiBridge::Registry — registry resolution
15
+ # RailsAiBridge::Tools — MCP tools
16
+ # RailsAiBridge::Serializers — output serializers
17
+ usage: opensource
18
+ integration: rspec
19
+ includes:
20
+ - lib
21
+ - spec
22
+ requires:
23
+ - spec_helper
24
+ fail_fast: false
25
+ mutation:
26
+ timeout: 5.0
data/.reek.yml CHANGED
@@ -87,6 +87,7 @@ detectors:
87
87
  - RailsAiBridge::Serializers::RegenerationFooter
88
88
  - RailsAiBridge::Introspectors::SemanticIntrospector
89
89
  - RailsAiBridge::RubydexAdapter::IncrementalIndexer
90
+ - RailsAiBridge::Registry::RegistryManifest
90
91
  DuplicateMethodCall:
91
92
  exclude:
92
93
  - RailsAiBridge::Config::Introspection#excluded_table?
@@ -416,6 +417,7 @@ detectors:
416
417
  - RailsAiBridge::Tools::BaseTool
417
418
  - RailsAiBridge::Watcher::BridgeRegenerator
418
419
  - RailsAiBridge::Fingerprinter::CachedSnapshot
420
+ - RailsAiBridge::Registry::RegistryManifest
419
421
  NestedIterators:
420
422
  exclude:
421
423
  - RailsAiBridge::Fingerprinter#snapshot
@@ -495,6 +497,7 @@ detectors:
495
497
  - RailsAiBridge::Introspectors::TestIntrospector
496
498
  - RailsAiBridge::Introspectors::ViewIntrospector
497
499
  - RailsAiBridge::RubydexAdapter
500
+ - RailsAiBridge::Registry::RegistryManifest
498
501
  - RailsAiBridge::Tools::GetStimulus::ResponseFormatter
499
502
  - RailsAiBridge::Tools::SearchSemantic
500
503
  TooManyInstanceVariables:
@@ -502,6 +505,7 @@ detectors:
502
505
  - RailsAiBridge::Config::Introspection
503
506
  - RailsAiBridge::Config::Mcp
504
507
  - RailsAiBridge::Config::Output
508
+ - RailsAiBridge::Config::Registry
505
509
  - RailsAiBridge::Config::Rubydex
506
510
  - RailsAiBridge::Config::Server
507
511
  - RailsAiBridge::Configuration
data/.rubocop.yml CHANGED
@@ -9,6 +9,7 @@ AllCops:
9
9
  - "vendor/**/*"
10
10
  - "spec/internal/**/*"
11
11
  - "gemfiles/**/*"
12
+ - ".mutant.yml"
12
13
  Naming/FileName:
13
14
  Exclude:
14
15
  - "lib/rails-ai-bridge.rb"
@@ -39,6 +40,8 @@ Layout/LineLength:
39
40
  Max: 180
40
41
  Metrics/ModuleLength:
41
42
  Max: 240
43
+ Exclude:
44
+ - "lib/rails_ai_bridge/resources.rb"
42
45
  Metrics/MethodLength:
43
46
  Max: 70
44
47
  RSpec/NestedGroups:
@@ -57,6 +60,12 @@ RSpec/MultipleDescribes:
57
60
  Enabled: false
58
61
  RSpec/MessageSpies:
59
62
  Enabled: false
63
+ RSpec/Output:
64
+ Exclude:
65
+ - "spec/support/perf_baseline.rb"
66
+ Rails/RakeEnvironment:
67
+ Exclude:
68
+ - "lib/tasks/*.rake"
60
69
  Metrics/PerceivedComplexity:
61
70
  Max: 35
62
71
  Exclude:
data/AGENTS.md CHANGED
@@ -8,9 +8,9 @@ structure to AI assistants via the Model Context Protocol (MCP).
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 **26** (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/` — 14 built-in MCP tools using the official mcp SDK (hosts can add more via `additional_tools`)
13
- - `lib/rails_ai_bridge/serializers/` — Output formatters (Codex, claude_rules, cursor_rules, devin, devin_rules, copilot, copilot_instructions, rules, markdown, JSON)
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/` — 17 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)
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)
16
16
  - `lib/rails_ai_bridge/middleware.rb` — Rack middleware for auto-mounting MCP HTTP endpoint
@@ -30,10 +30,10 @@ structure to AI assistants via the Model Context Protocol (MCP).
30
30
  6. **Diff-aware** — context regeneration skips unchanged files
31
31
  7. **Per-assistant serializers** — each AI tool gets tailored output format
32
32
  8. **Zeitwerk autoloading** — files loaded on-demand, not all upfront
33
- 9. **Introspector presets** — `:standard` (9 core) default, `:full` (26 introspectors; optional extras such as `database_stats`, `non_ar_models`) for power users
33
+ 9. **Introspector presets** — `:standard` (9 core) default, `:full` (27 introspectors; optional extras such as `database_stats`, `non_ar_models`) for power users
34
34
  10. **MCP auto-discovery** — `.mcp.json` generated by install generator
35
35
  11. **Compact by default** — context files ≤150 lines, MCP tools use `detail` parameter (summary/standard/full)
36
- 12. **Per-tool split rules** — `.Codex/rules/`, `.cursor/rules/`, `.devin/rules/`, `.github/instructions/`
36
+ 12. **Per-tool split rules** — `.codex/`, `.cursor/rules/`, `.devin/rules/`, `.github/instructions/`
37
37
 
38
38
  ## Testing
39
39
 
data/CHANGELOG.md CHANGED
@@ -5,7 +5,48 @@ 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
- ## [Unreleased]
8
+ ## [4.2.0] - 2026-08-13
9
+
10
+ ### Added
11
+
12
+ - **`rails_list_context_providers` MCP tool and dynamic resources** (#147) — new tool reads the registry manifest's `context_providers` section and returns formatted markdown with provider name, type, endpoint, optional flag, and tool specs. Context providers are also registered as dynamic MCP resources (URI template `rails://context-providers/{name}`), bringing the tool count from 16 to 17.
13
+ - **Registry health checker for Doctor** (#145) — new `Doctor::Checkers::RegistryChecker` validates manifest existence, JSON parsing, `RegistryManifest.validate!`, resolver construction, and lockfile presence (when configured). Returns pass/warn/fail with actionable fix hints. Doctor check count: 17.
14
+ - **Request-level resolver memoization** (#159) — `Registry.with_request_resolver` wraps each tool invocation in a thread-local request scope so `build_resolver` is called once per request instead of once per tool. Nil results are never memoized; thread-local storage is always cleaned up (even on error).
15
+ - **Dependabot configuration** (#153) — `.github/dependabot.yml` with grouped updates for bundler, github-actions, and gomod ecosystems, plus automatic PR labeling.
16
+ - **Rails 8.1 in release workflow matrix** (#164) — `.github/workflows/release.yml` now includes Rails 8.1 alongside 7.1, 7.2, and 8.0.
17
+ - **Skunk score threshold CI job** (#157) — advisory CI job runs `skunk lib/` after tests generate coverage data, fails if the SkunkScore average exceeds 30. Threshold to be ratcheted down over time.
18
+ - **Performance regression baseline** (#160) — `spec/support/perf_baseline.json` with three metrics (introspection, context generation, MCP tool response). `rake perf:compare` fails on >20% regression. CI uploads the baseline as a 30-day artifact.
19
+ - **Mutation testing for critical paths** (#163) — `mutant-rspec` via separate `Gemfile-mutation` (eval'd from the main Gemfile) to avoid breaking Ruby 3.2 CI resolution. Advisory CI job targets `Registry::Resolver`, `FrontmatterParser`, `RegistryManifest`, `PackResolver`, `SkillSourceResolver`, and key tools/serializers. Initial coverage: 94.39% on `FrontmatterParser`.
20
+ - **YARD documentation for 9 uncovered files** (#156) — `@param`/`@return` tags added to `search_code.rb`, all 6 introspectors, `json_serializer.rb`, and `usage_formatter.rb`. `yard stats` now 100% for `lib/`.
21
+ - **Dedicated `UsageFormatter` spec** (#151) — comprehensive spec coverage for `Tools::UsageFormatter` formatting logic.
22
+ - **Registry server specs and integration tests** (#149, #150) — `server_spec.rb` extended with registry tool assertions; new `mcp/registry_integration_spec.rb` covers `rails_list_registry`, `rails_resolve_skill`, and `rails_use_skill` end-to-end through the MCP server.
23
+ - **Documentation parity guard spec** — `spec/lib/rails_ai_bridge/doc_parity_spec.rb` fails when README/AGENTS/CLAUDE tool or introspector counts drift from the actual constants.
24
+
25
+ ### Changed
26
+
27
+ - **Standardized registry manifest and lockfile paths** (#155) — defaults changed from `config/rails_ai_bridge_registry.json` / `config/rails_ai_bridge_registry.lock` to `config/rails_ai_bridge/registry.json` / `config/rails_ai_bridge/registry.lock`. Backward-compat fallback: when the new path doesn't exist but the legacy path does, the getter returns the legacy path. Custom user paths are never overridden.
28
+ - **Documentation humanization and Windsurf purge** (#144, #148) — README, AGENTS.md, CLAUDE.md, CONTRIBUTING.md, and SECURITY.md updated: tool count 16→17, introspector count 26→27, serializer list humanized (alphabetical with Claude/Codex/Gemini), bogus `.Codex/rules/` path fixed to `.codex/`, Windsurf support claims removed (no serializer will be implemented), Mermaid diagrams added to docs.
29
+
30
+ ### Fixed
31
+
32
+ - **`Instrumentation::InstrumentedTool` server_context parameter translation** — tools without caching received `server_context:` but expected `_server_context:`, causing `ArgumentError` when caching was disabled. `InstrumentedTool` now detects the tool's parameter name and translates accordingly.
33
+ - **`ContextProvider` cache key fork safety** (#162) — replaced `object_id`-based cache key with a stable digest, preventing stale cache hits after `Process.fork`.
34
+
35
+ ## [4.1.0] - 2026-08-11
36
+
37
+ ### Added
38
+
39
+ - **JWT authentication docs for the HTTP MCP transport** (#129) — `docs/mcp-security.md` now documents the `mcp_jwt_decoder` pattern with a worked `JWT.decode` example, the decoder return-value contract, and a token rotation strategy (short expiry, signing-key overlap windows, revocation guidance).
40
+ - **`rails_use_skill` / `rails_use_agent` MCP tools** (#133) — resolve a skill or agent via `Registry::Resolver` and 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_skill` remains the read-only inspection tool (with `pack=` pinning).
41
+ - **JSON output for the registry rake tasks** (#128) — `rails "ai:skills:list[json]"` (or `FORMAT=json rails ai:skills:list`) prints a stable `{"packs": [...], "skills": [...]}` catalog document for CI and custom tooling. `RakePresenter` gains `skills_json`, `packs_json`, and `catalog_json`; the default table output is unchanged.
42
+ - **Transitive `depends_on` loading for skill packs** (#126) — opt in with `config.registry.auto_load_dependencies = true` (default `false`): `PackResolver` expands 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.
43
+ - **Structured logging for registry git operations** (#131) — `SkillSourceResolver` accepts an optional `logger:` (defaults to `Rails.logger`, or a stderr logger outside Rails). Clone, pull, and checkout operations log `key=value` lines: DEBUG before the operation, INFO with `duration_ms` on success, ERROR with the failure message before raising.
44
+ - **Context provider definitions in the registry manifest** (#134) — new `Registry::ContextProviderDefinition` and `Registry::ContextToolSpec` value objects (ported from the Rust runtime) parse an optional `context_providers` section of the registry manifest: provider `type`/`endpoint`, optional flag, and tool lists supporting both simple names and `{ name, field, arguments }` mappings. `RegistryManifest#context_providers` defaults to `{}` — parsing is preparatory and nothing consumes these definitions yet.
45
+ - **Manifest schema validation** (#123) — new `RegistryManifest.validate!` raises a descriptive `RegistryManifest::ValidationError` for the first invalid field (missing/empty pack `source`; wrong types for `version`, `default_stack`, `ref`, `tile`, `depends_on`, `always_loaded`, `priority`; non-object `packs` entries). New `rails ai:registry:validate` rake task validates the configured manifest for CI/pre-commit use and exits non-zero on failure.
46
+
47
+ ### Changed (breaking)
48
+
49
+ - **Full SHA-256 digests for skill-pack cache keys** (#122) — `SkillSourceResolver.compute_cache_key` now 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/cache` to reclaim disk space.
9
50
 
10
51
  ## [4.0.0] - 2026-08-09
11
52
 
data/CLAUDE.md CHANGED
@@ -9,14 +9,14 @@ structure to AI assistants via the Model Context Protocol (MCP).
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
11
  - `lib/rails_ai_bridge/introspectors/` — Built-in introspector classes; `:standard` preset
12
- runs **9**, `:full` runs **26** (see `Configuration::PRESETS`). Registry:
12
+ runs **9**, `:full` runs **27** (see `Configuration::PRESETS`). Registry:
13
13
  `Introspector::BUILTIN_INTROSPECTORS` (includes opt-in symbols such as
14
14
  `database_stats`, `non_ar_models` not listed in those presets).
15
- - `lib/rails_ai_bridge/tools/` — 14 built-in MCP tools using the official mcp SDK
15
+ - `lib/rails_ai_bridge/tools/` — 17 built-in MCP tools using the official mcp SDK
16
16
  (hosts can add more via `additional_tools`)
17
17
  - `lib/rails_ai_bridge/serializers/` — Output formatters (claude, claude_rules,
18
- cursor_rules, devin, devin_rules, copilot, copilot_instructions, rules,
19
- markdown, JSON)
18
+ codex, cursor_rules, devin, devin_rules, copilot, copilot_instructions,
19
+ gemini, rules, markdown, JSON)
20
20
  - `lib/rails_ai_bridge/resources.rb` — MCP resources (static data AI clients read directly)
21
21
  - `lib/rails_ai_bridge/server.rb` — MCP server configuration (stdio + HTTP transports)
22
22
  - `lib/rails_ai_bridge/middleware.rb` — Rack middleware for auto-mounting MCP HTTP endpoint
@@ -36,7 +36,7 @@ structure to AI assistants via the Model Context Protocol (MCP).
36
36
  6. **Diff-aware** — context regeneration skips unchanged files
37
37
  7. **Per-assistant serializers** — each AI tool gets tailored output format
38
38
  8. **Zeitwerk autoloading** — files loaded on-demand, not all upfront
39
- 9. **Introspector presets** — `:standard` (9 core) default, `:full` (26 introspectors; optional extras such as `database_stats`, `non_ar_models`) for power users
39
+ 9. **Introspector presets** — `:standard` (9 core) default, `:full` (27 introspectors; optional extras such as `database_stats`, `non_ar_models`) for power users
40
40
  10. **MCP auto-discovery** — `.mcp.json` generated by install generator
41
41
  11. **Compact by default** — context files ≤150 lines, MCP tools use `detail` parameter (summary/standard/full)
42
42
  12. **Per-tool split rules** — `.claude/rules/`, `.cursor/rules/`, `.devin/rules/`, `.github/instructions/`
data/CONTRIBUTING.md CHANGED
@@ -19,13 +19,13 @@ 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/ # 11 built-in MCP tools (detail levels, pagination, extensible)
22
+ ├── tools/ # 17 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, …)
26
26
  │ ├── indexer.rb # Graph building + source file scanning
27
27
  │ └── method_counter.rb # Flat method counting pipeline (no nested conditionals)
28
- ├── serializers/ # Per-assistant formatters (claude, cursor, windsurf, copilot, JSON)
28
+ ├── serializers/ # Per-assistant formatters (claude, codex, cursor, devin, copilot, gemini, JSON)
29
29
  ├── server.rb # MCP server setup (stdio + HTTP)
30
30
  ├── engine.rb # Rails Engine for auto-integration
31
31
  └── configuration.rb # User-facing config (presets, context_mode, limits)
data/GEMINI.md CHANGED
@@ -9,7 +9,7 @@ structure to AI assistants via the Model Context Protocol (MCP).
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
11
  - `lib/rails_ai_bridge/introspectors/` — Built-in introspector classes; `:standard` preset runs **9**, `:full` runs **26** (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/` — 11 built-in MCP tools using the official mcp SDK (hosts can add more via `additional_tools`)
12
+ - `lib/rails_ai_bridge/tools/` — 16 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, cursor_rules, windsurf, windsurf_rules, copilot, copilot_instructions, rules, markdown, JSON, gemini)
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)
data/README.md CHANGED
@@ -83,7 +83,7 @@ This creates two complementary layers:
83
83
  | Static files | Give the assistant passive project orientation at session start | Fewer cold starts and fewer generic assumptions |
84
84
  | MCP tools | Return exact live details when requested | Less context bloat and fewer schema/route hallucinations |
85
85
 
86
- Compact files are ordered for usefulness: primary domain models, busy endpoints, recently migrated tables, and optional hot-table signals appear before lower-signal supporting details.
86
+ Compact files are ordered for usefulness: primary domain models, busy endpoints, recently migrated tables, and optional hot-table hints appear before less important details.
87
87
 
88
88
  ## Safety model
89
89
 
@@ -159,7 +159,7 @@ Optional: `gem install rails-ai-bridge` installs the gem into your Ruby environm
159
159
  | Zero config | Yes — Railtie + install generator | No — per-project `projects.yml` | No |
160
160
  | Token optimization | Yes — compact files + `detail:"summary"` workflow | Varies | No |
161
161
  | Codex-oriented repo files | Yes — `AGENTS.md`, `.codex/README.md` | No | DIY |
162
- | Live MCP tools | Yes — 13 read-only `rails_*` tools (extensible) | Yes | No |
162
+ | Live MCP tools | Yes — 17 read-only `rails_*` tools (extensible) | Yes | No |
163
163
  | Auto-introspection | Yes — up to **27** domains (`:full`) | No — server points at projects you configure | DIY |
164
164
 
165
165
  *Comparison reflects typical documented setups; verify against each project before treating any row as absolute.*
@@ -251,7 +251,7 @@ This keeps context focused and avoids unnecessary token usage while still allowi
251
251
 
252
252
  ## MCP Tools
253
253
 
254
- The gem exposes **13 built-in tools** via MCP that AI clients call on-demand (hosts can append more via `config.additional_tools`):
254
+ The gem exposes **17 built-in tools** via MCP that AI clients call on-demand (hosts can append more via `config.additional_tools`):
255
255
 
256
256
  | Tool | What it returns |
257
257
  |------|----------------|
@@ -267,7 +267,11 @@ The gem exposes **13 built-in tools** via MCP that AI clients call on-demand (ho
267
267
  | `rails_get_view` | View layouts, templates, partials; optional per-file detail under the configured `app/views` path |
268
268
  | `rails_search_semantic` | Semantic code search using rubydex — find declarations by name with types, locations, and relationships |
269
269
  | `rails_get_stimulus` | Stimulus controllers: targets, values, actions, outlets (requires `:stimulus` introspector) |
270
- | `rails_list_registry` | Skill pack catalog — list skills, agents, or active packs; requires `config/rails_ai_bridge_registry.json` |
270
+ | `rails_list_registry` | Skill pack catalog — list skills, agents, or active packs; requires `config/rails_ai_bridge/registry.json` |
271
+ | `rails_resolve_skill` | Full content of a named skill or agent from the registry (priority ordering + deprecation redirects); optional `pack=` pin and `type=agent` |
272
+ | `rails_use_skill` | Loads a skill framed as an application directive (apply it step by step to the current task) |
273
+ | `rails_use_agent` | Loads an agent/workflow framed as an activation directive (follow it end to end) |
274
+ | `rails_list_context_providers` | Context providers declared in the registry manifest — external services (e.g. MCP servers) the bridge can query for project context; shows type, endpoint, optional flag, and tool specs |
271
275
 
272
276
  All tools are **read-only** — they never modify your application or database.
273
277
 
@@ -304,7 +308,7 @@ A safety net (`max_tool_response_chars`, default 120K) truncates oversized respo
304
308
 
305
309
  Early project-level trials suggest the biggest improvement is not always dramatic token reduction by itself. In several runs, `rails-ai-bridge` led to faster, more focused responses even when total token usage only dropped modestly.
306
310
 
307
- This is expected: compact assistant-specific files and the summary-first MCP workflow reduce orientation overhead, help the model navigate the codebase earlier, and improve the quality of the initial context.
311
+ This makes sense: compact assistant-specific files and the summary-first MCP workflow help the model find relevant code faster and start with better context.
308
312
 
309
313
  Observed benefits so far:
310
314
  - Less exploratory reading before the assistant reaches the relevant files
@@ -540,13 +544,14 @@ end
540
544
  | `parallel_introspection` | `false` | Run introspectors concurrently (requires `concurrent-ruby`, which is already a Rails dependency) |
541
545
  | `parallel_pool_size` | `4` | Max threads in the parallel pool; capped at the number of active introspectors so no idle threads are created |
542
546
  | `parallel_timeout_seconds` | `10` | Per-introspector future timeout (seconds); timed-out introspectors return `{ error: "timed out after Ns" }` without blocking the others |
543
- | `registry.registry_manifest_path` | `"config/rails_ai_bridge_registry.json"` | Path to the registry manifest JSON file for skill pack resolution |
547
+ | `registry.registry_manifest_path` | `"config/rails_ai_bridge/registry.json"` | Path to the registry manifest JSON file for skill pack resolution |
544
548
  | `registry.skill_cache_dir` | `"~/.rails-ai-bridge/cache"` | Directory for caching git repositories containing skill packs |
545
549
  | `registry.skill_packs` | `nil` | Explicit pack names to load, or `nil` for auto-detection based on framework |
546
550
  | `registry.local_registry_paths` | `[]` | Local directory paths (must contain `directory.json`) loaded at priority 0 |
547
551
  | `registry.resolver_ttl` | `1800` | Seconds to cache the wired resolver in memory; `0` disables caching |
548
552
  | `registry.git_pull_ttl` | `86400` | Seconds between `git pull` refreshes per cached pack (24 h default). Set to `0` to pull on every resolver rebuild |
549
553
  | `registry.git_timeout` | `30` | Seconds before a git operation (clone, pull, checkout) is forcibly interrupted |
554
+ | `registry.auto_load_dependencies` | `false` | Load declared `depends_on` packs transitively; circular chains warn but still load |
550
555
 
551
556
  Other HTTP MCP knobs live only on the nested object, for example `RailsAiBridge.configuration.mcp.authorize`, `mcp.mode`, `mcp.security_profile`, and `mcp.require_auth_in_production` — see [docs/GUIDE.md](docs/GUIDE.md) and [docs/mcp-security.md](docs/mcp-security.md).
552
557
  </details>
@@ -682,10 +687,10 @@ To customize it in your initializer (`config/initializers/rails_ai_bridge.rb`):
682
687
  rails-ai-bridge can load **skill packs** — shared collections of agent instructions — from versioned git repositories and surface them through `rails_list_registry` and rake tasks.
683
688
 
684
689
  ```ruby
685
- config.registry.registry_manifest_path = "config/rails_ai_bridge_registry.json"
690
+ config.registry.registry_manifest_path = "config/rails_ai_bridge/registry.json"
686
691
  ```
687
692
 
688
- Quick example manifest (`config/rails_ai_bridge_registry.json`):
693
+ Quick example manifest (`config/rails_ai_bridge/registry.json`):
689
694
 
690
695
  ```json
691
696
  {
@@ -831,7 +836,7 @@ Bug reports and pull requests: [github.com/igmarin/rails-ai-bridge/issues](https
831
836
 
832
837
  ## Acknowledgments & Origins
833
838
 
834
- This gem ships as **rails-ai-bridge** (Ruby **`RailsAiBridge`**, version **3.6.2**). Earlier iterations of the same codebase were distributed as `rails-ai-context`.
839
+ This gem ships as **rails-ai-bridge** (Ruby **`RailsAiBridge`**, version **4.2.0**). Earlier iterations of the same codebase were distributed as `rails-ai-context`.
835
840
 
836
841
  RailsMCP evolved from
837
842
  [crisnahine/rails-ai-context](https://github.com/crisnahine/rails-ai-context),
data/Rakefile CHANGED
@@ -5,4 +5,6 @@ require 'rspec/core/rake_task'
5
5
 
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
8
+ Dir.glob('lib/tasks/*.rake').each { |task| load task }
9
+
8
10
  task default: :spec
data/SECURITY.md CHANGED
@@ -4,10 +4,10 @@
4
4
 
5
5
  | Version | Supported |
6
6
  |---------|--------------------|
7
- | 3.6.x | :white_check_mark: |
8
- | 3.5.x | :white_check_mark: |
9
- | 3.0.x–3.4.x | :white_check_mark: (security fixes best-effort) |
10
- | 2.x | :x: (end of life — upgrade to 3.x) |
7
+ | 4.x | :white_check_mark: |
8
+ | 3.6.x | :white_check_mark: (security fixes best-effort) |
9
+ | 3.0.x–3.5.x | :warning: (best-effort) |
10
+ | 2.x | :x: (end of life — upgrade to 4.x) |
11
11
  | 1.x | :x: |
12
12
  | < 1.0 | :x: |
13
13
 
@@ -0,0 +1,152 @@
1
+ # Plan 2: Port Registry Resolution from Rust Runtime to rails-ai-bridge
2
+
3
+ **Status:** Complete ✅ — implemented via PRs #40–#45
4
+ **Priority:** After Plan 1
5
+ **Estimated effort:** 4 weeks
6
+ **Depends on:** Plan 1 (agent-mcp-runtime archived)
7
+
8
+ > **Completion note (2026-08-10):** All success criteria shipped. See
9
+ > [`port-registry-resolution.md`](port-registry-resolution.md) for as-built decisions and deltas, and
10
+ > [`registry-resolution.md`](registry-resolution.md) for user-facing documentation. Naming deltas from
11
+ > this plan: rake tasks shipped as `ai:skills:list` / `ai:skills:resolve[pack,name]` (planned:
12
+ > `ai:list_skills` / `ai:resolve_skill`); configuration lives under `config.registry.*`
13
+ > (`Config::Registry`); the MCP surface is the unified `rails_list_registry` tool plus
14
+ > `rails_resolve_skill`; git operations use `Open3` (stdlib) — no `git` gem dependency.
15
+
16
+ ## Objective
17
+
18
+ Port the registry resolution logic from `agent-mcp-runtime` (Rust) into `rails-ai-bridge` (Ruby). This enables the bridge to resolve skill packs from git repositories, handle priority-based loading, and support deprecation redirects — all necessary for the future skill compiler feature.
19
+
20
+ ## Components to Port
21
+
22
+ ### 1. New module: `lib/rails_ai_bridge/registry/`
23
+
24
+ #### `lib/rails_ai_bridge/registry/manifest.rb`
25
+ - Port `RegistryManifest` struct from Rust (version, packs, default_stack, context_providers)
26
+ - Port `PackDefinition` struct (source, tile, always_loaded, depends_on)
27
+ - Port `ContextProviderDefinition` and `ContextToolSpec` (for future context provider integration)
28
+ - Use JSON parsing with `json` gem (already in rails-ai-bridge dependencies)
29
+
30
+ #### `lib/rails_ai_bridge/registry/tile_manifest.rb`
31
+ - Port `TileManifest` struct (name, version, summary, depends_on, skills, agents, deprecated_skills)
32
+ - Port `SkillEntry` and `AgentEntry` structs
33
+ - Port `DeprecatedEntry` struct (moved_to, message, removed_in)
34
+
35
+ #### `lib/rails_ai_bridge/registry/git_source_resolver.rb`
36
+ - Port `SkillSourceResolver` from Rust
37
+ - Implement git clone/pull using `git` gem or shell commands
38
+ - Cache directory: `~/.rails-ai-bridge/cache/` (instead of `~/.agent-mcp-runtime/cache/`)
39
+ - Support local path resolution (sibling directories for development)
40
+ - Implement `GitRunner` trait pattern with a default implementation and test mock
41
+
42
+ #### `lib/rails_ai_bridge/registry/pack_detector.rb`
43
+ - Port `PackDetector` from Rust
44
+ - Parse Gemfile to detect Rails vs Hanami
45
+ - Return array of detected frameworks
46
+
47
+ #### `lib/rails_ai_bridge/registry/pack_resolver.rb`
48
+ - Port `PackResolverService` logic
49
+ - Implement priority-based pack loading:
50
+ - Priority 0: Local registries (--registry flag)
51
+ - Priority 10: Framework packs (rails, hanami)
52
+ - Priority 20: Core pack (always_loaded)
53
+ - Priority 30: Default stack (planning)
54
+ - Handle explicit pack overrides
55
+ - Load tile.json manifests from resolved sources
56
+ - Return `RegistryResolver` instance
57
+
58
+ #### `lib/rails_ai_bridge/registry/resolver.rb`
59
+ - Port `RegistryResolver` from Rust
60
+ - Implement `LoadedPack` struct (name, tile, base_path, priority)
61
+ - Implement `ResolvedSkill` struct (name, pack, path, content)
62
+ - Implement `SkillSummary` struct (name, pack, description)
63
+ - Implement `resolve_skill(name)` with deprecation redirect handling
64
+ - Implement `resolve_agent(name)`
65
+ - Implement `list_skills()` with deduplication by priority
66
+ - Implement `validate_dependencies()` to warn on missing dependencies
67
+ - Sort packs by priority (ascending = higher priority)
68
+
69
+ #### `lib/rails_ai_bridge/registry.rb`
70
+ - Main registry module that requires all submodules
71
+ - Public API entry point
72
+
73
+ ### 2. Integration with rails-ai-bridge
74
+
75
+ **Add to `lib/rails_ai_bridge.rb`:**
76
+ - Require the new registry module
77
+ - Add convenience method `RailsAiBridge.resolve_skill(pack_name, skill_name)`
78
+ - Add convenience method `RailsAiBridge.list_skills()`
79
+
80
+ **Create new Rake task: `lib/rails_ai_bridge/tasks/registry.rake`**
81
+
82
+ ```ruby
83
+ namespace :rails_ai_bridge do
84
+ desc "List all available skills from configured packs"
85
+ task list_skills: :environment do
86
+ # Use registry resolver to list skills
87
+ end
88
+
89
+ desc "Resolve a specific skill"
90
+ task :resolve_skill, [:pack, :skill] => :environment do |t, args|
91
+ # Resolve and print skill content
92
+ end
93
+ end
94
+ ```
95
+
96
+ ### 3. Configuration
97
+
98
+ **Add to `lib/rails_ai_bridge/configuration.rb`:**
99
+ - `registry_manifest_path` — Path to registry.json (default: `config/rails_ai_bridge/registry.json`)
100
+ - `skill_cache_dir` — Path to git cache directory (default: `~/.rails-ai-bridge/cache`)
101
+ - `skill_packs` — Array of explicit pack names to load (optional)
102
+ - `local_registry_paths` — Array of local registry directories (optional)
103
+
104
+ ### 4. Tests
105
+
106
+ **Create spec directory: `spec/rails_ai_bridge/registry/`**
107
+ - `manifest_spec.rb`
108
+ - `tile_manifest_spec.rb`
109
+ - `git_source_resolver_spec.rb` (with mock git runner)
110
+ - `pack_detector_spec.rb`
111
+ - `pack_resolver_spec.rb`
112
+ - `resolver_spec.rb`
113
+
114
+ Use the Rust tests in `agent-mcp-runtime/src/registry/pack_resolver.rs` and `resolver.rs` as reference for test cases.
115
+
116
+ ### 5. Documentation
117
+
118
+ **Create `docs/registry-resolution.md`** inside rails-ai-bridge:
119
+ - Explain the registry resolution system
120
+ - Document priority rules
121
+ - Provide example registry.json configuration
122
+ - Document configuration options
123
+
124
+ ### 6. Dependencies
125
+
126
+ Add to `rails-ai-bridge.gemspec` if not already present:
127
+ - `git` gem (for git operations) — check if already present
128
+ - Ensure `json` gem is available (standard library in Ruby 3+)
129
+
130
+ ## Implementation Order
131
+
132
+ 1. **Week 1:** Create manifest and tile_manifest structs with tests; create git_source_resolver with mock for tests
133
+ 2. **Week 2:** Create pack_detector and pack_resolver with tests
134
+ 3. **Week 3:** Create resolver with tests; integrate with rails-ai-bridge main module
135
+ 4. **Week 4:** Add Rake tasks, configuration, and documentation
136
+
137
+ ## Notes
138
+
139
+ - The existing `ruby-skill-bench` has a `PackResolver` class that does similar work. Review it for patterns but don't directly copy — the bridge version needs git resolution and priority handling that the bench version lacks.
140
+ - The Rust runtime uses async/await. Ruby doesn't have this — use synchronous git operations.
141
+ - Cache directory should be `~/.rails-ai-bridge/cache/` to avoid conflicts with the archived runtime.
142
+ - Framework detection: just check Gemfile for `'rails'` or `'hanami'` gems.
143
+ - Deprecation handling is critical for the skill migration from `rails-agent-skills` to `ruby-core-skills` already in progress.
144
+
145
+ ## Success Criteria
146
+
147
+ - [x] All 6 registry modules created with passing specs (323 registry/config/tool examples green, 2026-08-10)
148
+ - [x] `rails ai:skills:list` Rake task works (shipped name; planned as `ai:list_skills`)
149
+ - [x] `rails "ai:skills:resolve[pack,name]"` Rake task works (shipped name; planned as `ai:resolve_skill[pack,name]`)
150
+ - [x] Documentation written (`docs/registry-resolution.md`)
151
+ - [x] Priority-based resolution handles core/rails/hanami/planning correctly
152
+ - [x] Deprecation redirects work (e.g., old skill name → new location)
data/docs/devin-setup.md CHANGED
@@ -226,7 +226,7 @@ rails-ai-bridge supports a skill registry — a collection of reusable AI skills
226
226
 
227
227
  The `rails_list_registry` tool returns all available skills. The `rails_resolve_skill` tool retrieves the full content of a named skill so Devin can apply it.
228
228
 
229
- Skills are configured via `config/rails_ai_bridge_registry.json` in your Rails application. A minimal registry file looks like:
229
+ Skills are configured via `config/rails_ai_bridge/registry.json` in your Rails application. A minimal registry file looks like:
230
230
 
231
231
  ```json
232
232
  {
@@ -261,4 +261,4 @@ Devin will call `rails_list_registry`, review the options, and call `rails_resol
261
261
  | `.devin/rules/rails-mcp-tools.md` | `rails ai:bridge:devin` | Yes |
262
262
  | `AGENTS.md` | `rails ai:bridge:devin` | Yes |
263
263
  | `.devin/mcp.json` | Manual | Yes |
264
- | `config/rails_ai_bridge_registry.json` | Manual | Yes |
264
+ | `config/rails_ai_bridge/registry.json` | Manual | Yes |
data/docs/mcp-security.md CHANGED
@@ -12,6 +12,59 @@ By default, HTTP MCP allows anonymous access when no auth strategy is configured
12
12
 
13
13
  In non-production environments, the standalone HTTP MCP server prints a one-time stderr warning when it starts without authentication to make the default behavior visible.
14
14
 
15
+ ## JWT authentication with short-lived tokens
16
+
17
+ `http_mcp_token` is a static bearer token: rotating it means redistributing a secret to every client. For deployments that need rotation or expiry, configure `config.mcp_jwt_decoder` instead — the highest-priority auth strategy. The gem carries **no JWT dependency**: you supply a lambda that decodes (and verifies) the token.
18
+
19
+ ```ruby
20
+ # config/initializers/rails_ai_bridge.rb
21
+ require "jwt" # the host app's own jwt gem
22
+
23
+ RailsAiBridge.configure do |config|
24
+ config.mcp.require_http_auth = true
25
+
26
+ config.mcp_jwt_decoder = ->(token) do
27
+ payload, _header = JWT.decode(
28
+ token,
29
+ Rails.application.credentials.jwt_mcp_secret!,
30
+ true, # verify signature
31
+ algorithm: "HS256",
32
+ verify_expiration: true # reject expired tokens (default when verifying)
33
+ )
34
+ payload # truthy payload => authenticated
35
+ rescue JWT::DecodeError, JWT::ExpiredSignature
36
+ nil # nil => 401 unauthorized
37
+ end
38
+ end
39
+ ```
40
+
41
+ Decoder contract:
42
+
43
+ - Return a **truthy payload** (Hash recommended) — request is authenticated; the payload is exposed to authorization hooks.
44
+ - Return **`nil`** or **`false`** — request is rejected with `401` (`:unauthorized`).
45
+ - **Raise** — treated as `:decode_error`, also `401`; the exception never propagates.
46
+
47
+ ### Token rotation strategy
48
+
49
+ - **Short expiry, frequent re-issue.** Issue MCP tokens with a 5–15 minute `exp` from your existing login/session flow. A leaked token expires on its own; there is nothing to rotate per incident.
50
+ - **Signing-key rotation.** When rotating the HMAC secret (or moving to RS256/JWKS), accept both keys during the overlap window:
51
+
52
+ ```ruby
53
+ config.mcp_jwt_decoder = ->(token) do
54
+ keys = [Rails.application.credentials.jwt_mcp_secret!,
55
+ Rails.application.credentials.jwt_mcp_secret_previous!]
56
+ keys.lazy.filter_map do |key|
57
+ JWT.decode(token, key, true, algorithm: "HS256").first
58
+ rescue JWT::DecodeError, JWT::ExpiredSignature
59
+ nil
60
+ end.first
61
+ end
62
+ ```
63
+
64
+ Retire the previous key once all clients have re-issued tokens.
65
+ - **Immediate revocation.** Stateless JWTs cannot be revoked; if you need it, combine short `exp` with your own denylist check inside the decoder (return `nil` for revoked subjects).
66
+ - **Client capability note.** Some AI hosts cannot refresh tokens and work best with a long-lived static token or `mcp_token_resolver` (which can consult a secret manager per request). Pick the strategy per client: JWT for short-lived machine-to-machine auth, `mcp_token_resolver` when the credential lives in a vault, `http_mcp_token` only for local development.
67
+
15
68
  ## Rate limiting and proxies
16
69
 
17
70
  Built-in rate limiting keys off the Rack request IP. Behind reverse proxies, configure Rails `trusted_proxies` so `request.ip` reflects the real client; otherwise limits may apply to the wrong address or be bypassed.
@@ -119,7 +119,7 @@ necessary for the future skill compiler feature.
119
119
 
120
120
  **Files:**
121
121
  - `lib/rails_ai_bridge/config/registry.rb` — `Config::Registry` sub-object
122
- - `registry_manifest_path` (default: `config/rails_ai_bridge_registry.json`)
122
+ - `registry_manifest_path` (default: `config/rails_ai_bridge/registry.json`)
123
123
  - `skill_cache_dir` (default: `~/.rails-ai-bridge/cache`)
124
124
  - `skill_packs` (default: `nil` — triggers auto-detection)
125
125
  - `local_registry_paths` (default: `[]`)
@@ -16,7 +16,7 @@ When a pack is loaded, its skills and agents appear in `rails_list_registry`, an
16
16
 
17
17
  ## Quick start
18
18
 
19
- **1. Create the registry manifest** at `config/rails_ai_bridge_registry.json`:
19
+ **1. Create the registry manifest** at `config/rails_ai_bridge/registry.json`:
20
20
 
21
21
  ```json
22
22
  {
@@ -39,7 +39,7 @@ When a pack is loaded, its skills and agents appear in `rails_list_registry`, an
39
39
 
40
40
  ```ruby
41
41
  RailsAiBridge.configure do |config|
42
- config.registry.registry_manifest_path = "config/rails_ai_bridge_registry.json"
42
+ config.registry.registry_manifest_path = "config/rails_ai_bridge/registry.json"
43
43
  end
44
44
  ```
45
45
 
@@ -102,7 +102,7 @@ All options live under `config.registry.*`:
102
102
 
103
103
  | Option | Default | Description |
104
104
  |--------|---------|-------------|
105
- | `registry_manifest_path` | `"config/rails_ai_bridge_registry.json"` | Path to the registry manifest JSON |
105
+ | `registry_manifest_path` | `"config/rails_ai_bridge/registry.json"` | Path to the registry manifest JSON |
106
106
  | `skill_cache_dir` | `~/.rails-ai-bridge/cache` | Directory for caching cloned git repositories |
107
107
  | `skill_packs` | `nil` | Explicit list of pack names to load, or `nil` for auto-detection |
108
108
  | `local_registry_paths` | `[]` | Local directory paths containing a `directory.json` (loaded at priority 0) |
@@ -200,9 +200,10 @@ Once a registry manifest is configured:
200
200
 
201
201
  | Task | Description |
202
202
  |------|-------------|
203
- | `rails ai:skills:list` | Print skill catalog to stdout |
203
+ | `rails ai:skills:list` | Print skill catalog to stdout; `[json]` argument (or `FORMAT=json`) prints a `{"packs": [...], "skills": [...]}` document |
204
204
  | `rails "ai:skills:resolve[pack,skill_name]"` | Resolve and print a skill's full content |
205
205
  | `rails ai:skills:clear_cache` | Remove all cached pack git repositories and invalidate the resolver cache |
206
+ | `rails ai:registry:validate` | Validate the registry manifest schema; exits non-zero on the first invalid field |
206
207
 
207
208
  Examples:
208
209