rails-ai-context 4.2.3 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/CLAUDE.md +4 -4
- data/CONTRIBUTING.md +1 -1
- data/README.md +7 -7
- data/SECURITY.md +1 -1
- data/docs/GUIDE.md +3 -3
- data/lib/generators/rails_ai_context/install/install_generator.rb +2 -2
- data/lib/rails_ai_context/serializers/claude_serializer.rb +30 -11
- data/lib/rails_ai_context/serializers/cursor_rules_serializer.rb +1 -1
- data/lib/rails_ai_context/serializers/opencode_serializer.rb +6 -2
- data/lib/rails_ai_context/serializers/tool_guide_helper.rb +159 -64
- data/lib/rails_ai_context/server.rb +5 -1
- data/lib/rails_ai_context/tools/diagnose.rb +309 -0
- data/lib/rails_ai_context/tools/generate_test.rb +519 -0
- data/lib/rails_ai_context/tools/onboard.rb +453 -0
- data/lib/rails_ai_context/tools/review_changes.rb +290 -0
- data/lib/rails_ai_context/version.rb +1 -1
- metadata +8 -4
|
@@ -24,20 +24,20 @@ module RailsAiContext
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def tools_header
|
|
27
|
-
"## Tools (
|
|
27
|
+
"## Tools (37) — MANDATORY, Use Before Read"
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def tools_intro
|
|
31
31
|
case tool_mode
|
|
32
32
|
when :cli
|
|
33
33
|
[
|
|
34
|
-
"This project has
|
|
34
|
+
"This project has 37 introspection tools. **MANDATORY — use these instead of reading files.**",
|
|
35
35
|
"They return only relevant, structured data and save tokens. Read files ONLY when you are about to Edit them.",
|
|
36
36
|
""
|
|
37
37
|
]
|
|
38
38
|
else
|
|
39
39
|
[
|
|
40
|
-
"This project has
|
|
40
|
+
"This project has 37 MCP tools via `rails ai:serve` (configured in `.mcp.json`).",
|
|
41
41
|
"**MANDATORY — use these instead of reading files.** They return structured data and save tokens.",
|
|
42
42
|
"Read files ONLY when you are about to Edit them.",
|
|
43
43
|
"If MCP tools are not connected, use CLI fallback: `#{cli_cmd("TOOL_NAME", "param=value")}`",
|
|
@@ -46,57 +46,92 @@ module RailsAiContext
|
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
def
|
|
49
|
+
def tools_detail_guidance
|
|
50
|
+
detail_param = tool_mode == :cli ? "detail=summary" : "detail:\"summary\""
|
|
50
51
|
[
|
|
51
|
-
"###
|
|
52
|
+
"### detail parameter — ALWAYS start with summary",
|
|
52
53
|
"",
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
"Most tools accept `#{detail_param}`. Use the right level:",
|
|
55
|
+
"- **summary** — first call, orient yourself (table list, model names, route overview)",
|
|
56
|
+
"- **standard** — working detail (columns with types, associations, action source) — DEFAULT",
|
|
57
|
+
"- **full** — only when you need indexes, foreign keys, code snippets, or complete content",
|
|
57
58
|
"",
|
|
58
|
-
"
|
|
59
|
-
|
|
59
|
+
"Pattern: summary to find the target → standard to understand it → full only if needed.",
|
|
60
|
+
""
|
|
61
|
+
]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def tools_power_tool_section
|
|
65
|
+
[
|
|
66
|
+
"### Start here — composite tools save multiple calls",
|
|
60
67
|
"",
|
|
61
|
-
"**
|
|
62
|
-
tool_call("
|
|
63
|
-
tool_call("rails_get_model_details(model:\"Cook\")", cli_cmd("model_details", "model=Cook")),
|
|
64
|
-
tool_call("rails_migration_advisor(action:\"add_column\", table:\"cooks\", column:\"rating\", type:\"integer\")", cli_cmd("migration_advisor", "action=add_column table=cooks column=rating type=integer")),
|
|
68
|
+
"**New to this project?** Get a full walkthrough first:",
|
|
69
|
+
tool_call("rails_onboard(detail:\"standard\")", cli_cmd("onboard", "detail=standard")),
|
|
65
70
|
"",
|
|
66
|
-
"**
|
|
67
|
-
tool_call("
|
|
71
|
+
"**`get_context` is your power tool** — bundles schema + model + controller + routes + views in ONE call:",
|
|
72
|
+
tool_call("rails_get_context(controller:\"CooksController\", action:\"create\")", cli_cmd("context", "controller=CooksController action=create")),
|
|
73
|
+
tool_call("rails_get_context(model:\"Cook\")", cli_cmd("context", "model=Cook")),
|
|
74
|
+
tool_call("rails_get_context(feature:\"cook\")", cli_cmd("context", "feature=cook")),
|
|
68
75
|
"",
|
|
69
|
-
"**
|
|
70
|
-
tool_call("
|
|
71
|
-
tool_call("rails_get_view(controller:\"cooks\")", cli_cmd("view", "controller=cooks")),
|
|
72
|
-
tool_call("rails_get_partial_interface(partial:\"shared/status_badge\")", cli_cmd("partial_interface", "partial=shared/status_badge")),
|
|
73
|
-
tool_call("rails_get_component_catalog(component:\"Alert\")", cli_cmd("component_catalog", "component=Alert")),
|
|
76
|
+
"**`analyze_feature` for broad discovery** — scans all layers (models, controllers, routes, services, jobs, views, tests):",
|
|
77
|
+
tool_call("rails_analyze_feature(feature:\"authentication\")", cli_cmd("analyze_feature", "feature=authentication")),
|
|
74
78
|
"",
|
|
75
|
-
"
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
"Use individual tools only when you need deeper detail on a specific layer.",
|
|
80
|
+
""
|
|
81
|
+
]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def tools_workflow_section # rubocop:disable Metrics/MethodLength
|
|
85
|
+
[
|
|
86
|
+
"### Step-by-step workflows (follow this order)",
|
|
78
87
|
"",
|
|
79
|
-
"**
|
|
80
|
-
|
|
81
|
-
|
|
88
|
+
"**Modify a model** (add field, change validation, add scope):",
|
|
89
|
+
"1. #{tool_call_inline("rails_get_context", "model:\"Cook\"", "context", "model=Cook")} — schema + associations + validations in one call",
|
|
90
|
+
"2. Read the model file, make your edit",
|
|
91
|
+
"3. #{tool_call_inline("rails_migration_advisor", "action:\"add_column\", table:\"cooks\", column:\"rating\", type:\"integer\"", "migration_advisor", "action=add_column table=cooks column=rating type=integer")} — if schema change needed",
|
|
92
|
+
"4. #{tool_call_inline("rails_validate", "files:[\"app/models/cook.rb\"], level:\"rails\"", "validate", "files=app/models/cook.rb level=rails")} — EVERY time after editing",
|
|
93
|
+
"5. #{tool_call_inline("rails_generate_test", "model:\"Cook\"", "generate_test", "model=Cook")} — generate tests matching project patterns",
|
|
82
94
|
"",
|
|
83
|
-
"**
|
|
84
|
-
|
|
95
|
+
"**Fix a controller bug:**",
|
|
96
|
+
"1. #{tool_call_inline("rails_get_context", "controller:\"CooksController\", action:\"create\"", "context", "controller=CooksController action=create")} — action source + routes + views + model",
|
|
97
|
+
"2. Read the controller file, make your fix",
|
|
98
|
+
"3. #{tool_call_inline("rails_validate", "files:[\"app/controllers/cooks_controller.rb\"], level:\"rails\"", "validate", "files=app/controllers/cooks_controller.rb level=rails")}",
|
|
85
99
|
"",
|
|
86
|
-
"**
|
|
87
|
-
|
|
100
|
+
"**Build or modify a view:**",
|
|
101
|
+
"1. #{tool_call_inline("rails_get_design_system", "detail:\"standard\"", "design_system", "detail=standard")} — get copy-paste HTML/ERB patterns",
|
|
102
|
+
"2. #{tool_call_inline("rails_get_view", "controller:\"cooks\"", "view", "controller=cooks")} — existing templates, partials, Stimulus refs",
|
|
103
|
+
"3. #{tool_call_inline("rails_get_partial_interface", "partial:\"shared/status_badge\"", "partial_interface", "partial=shared/status_badge")} — partial locals contract",
|
|
104
|
+
"4. Read the view file, make your edit",
|
|
105
|
+
"5. #{tool_call_inline("rails_validate", "files:[\"app/views/cooks/index.html.erb\"]", "validate", "files=app/views/cooks/index.html.erb")}",
|
|
88
106
|
"",
|
|
89
|
-
"**
|
|
90
|
-
tool_call("
|
|
107
|
+
"**Trace a method:**",
|
|
108
|
+
tool_call("rails_search_code(pattern:\"can_cook?\", match_type:\"trace\")", cli_cmd("search_code", "pattern=\"can_cook?\" match_type=trace")),
|
|
91
109
|
"",
|
|
92
|
-
"**Debug
|
|
93
|
-
tool_call("
|
|
110
|
+
"**Debug an error (one call — gathers context + git + logs + fix):**",
|
|
111
|
+
tool_call("rails_diagnose(error:\"NoMethodError: undefined method `foo` for nil\", file:\"app/models/cook.rb\")", cli_cmd("diagnose", "error=\"NoMethodError: undefined method foo\" file=app/models/cook.rb")),
|
|
94
112
|
"",
|
|
95
|
-
"**
|
|
96
|
-
tool_call("
|
|
113
|
+
"**Review changes before merging:**",
|
|
114
|
+
tool_call("rails_review_changes(ref:\"main\")", cli_cmd("review_changes", "ref=main")),
|
|
97
115
|
"",
|
|
98
|
-
"**
|
|
99
|
-
tool_call("
|
|
116
|
+
"**Generate tests matching project patterns:**",
|
|
117
|
+
tool_call("rails_generate_test(model:\"Cook\")", cli_cmd("generate_test", "model=Cook")),
|
|
118
|
+
""
|
|
119
|
+
]
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def tools_antipatterns_section
|
|
123
|
+
search_tool = tool_mode == :cli ? cli_cmd("search_code") : "rails_search_code"
|
|
124
|
+
validate_tool = tool_mode == :cli ? cli_cmd("validate") : "rails_validate"
|
|
125
|
+
[
|
|
126
|
+
"### Common mistakes — avoid these",
|
|
127
|
+
"",
|
|
128
|
+
"- **Don't read db/schema.rb** — use `get_schema`. It adds [indexed]/[unique] hints you'd miss.",
|
|
129
|
+
"- **Don't read model files for reference** — use `get_model_details`. It resolves concerns, inherited methods, and implicit belongs_to validations.",
|
|
130
|
+
"- **Don't use Grep/search agents** — use `#{search_tool}`. It excludes sensitive files, supports `match_type:\"trace\"`, and paginates.",
|
|
131
|
+
"- **Don't call tools without a target** — `get_model_details()` without `model:` returns a paginated list, not an error. Always specify what you want.",
|
|
132
|
+
"- **Don't skip validation** — run `#{validate_tool}` after EVERY edit. It catches syntax errors AND Rails-specific issues (missing partials, bad column refs).",
|
|
133
|
+
"- **Don't ignore cross-references** — tool responses include `_Next:` hints suggesting the best follow-up call. Follow them.",
|
|
134
|
+
"- **Don't call `detail:\"full\"` first** — start with `summary` to find your target, then drill in. Full responses waste tokens.",
|
|
100
135
|
""
|
|
101
136
|
]
|
|
102
137
|
end
|
|
@@ -107,30 +142,32 @@ module RailsAiContext
|
|
|
107
142
|
[
|
|
108
143
|
"### Rules",
|
|
109
144
|
"",
|
|
110
|
-
"1.
|
|
111
|
-
"2. NEVER
|
|
112
|
-
"3. NEVER
|
|
113
|
-
"4. Read files ONLY
|
|
114
|
-
"5.
|
|
145
|
+
"1. **Use composite tools first** — `#{cli_cmd("context")}` and `#{cli_cmd("analyze_feature")}` before individual tools",
|
|
146
|
+
"2. **NEVER read reference files** — db/schema.rb, config/routes.rb, model files, test files — tools are better",
|
|
147
|
+
"3. **NEVER use Grep** — use `#{cli_cmd("search_code")}`",
|
|
148
|
+
"4. **Read files ONLY to Edit them** — not for reference",
|
|
149
|
+
"5. **Validate EVERY edit** — `#{cli_cmd("validate", "files=... level=rails")}`",
|
|
150
|
+
"6. **Follow _Next:_ hints** — tool responses suggest the best follow-up call",
|
|
115
151
|
""
|
|
116
152
|
]
|
|
117
153
|
else
|
|
118
154
|
[
|
|
119
155
|
"### Rules",
|
|
120
156
|
"",
|
|
121
|
-
"1.
|
|
122
|
-
"2. NEVER
|
|
123
|
-
"3. NEVER
|
|
124
|
-
"4. Read files ONLY
|
|
125
|
-
"5.
|
|
126
|
-
"6.
|
|
157
|
+
"1. **Use composite tools first** — `rails_get_context` and `rails_analyze_feature` before individual tools",
|
|
158
|
+
"2. **NEVER read reference files** — db/schema.rb, config/routes.rb, model files, test files — tools are better",
|
|
159
|
+
"3. **NEVER use Grep** — use `rails_search_code`",
|
|
160
|
+
"4. **Read files ONLY to Edit them** — not for reference",
|
|
161
|
+
"5. **Validate EVERY edit** — `rails_validate(files:[...], level:\"rails\")`",
|
|
162
|
+
"6. **Follow _Next:_ hints** — tool responses suggest the best follow-up call",
|
|
163
|
+
"7. If MCP tools are not connected, use CLI: `#{cli_cmd("TOOL_NAME", "param=value")}`",
|
|
127
164
|
""
|
|
128
165
|
]
|
|
129
166
|
end
|
|
130
167
|
end
|
|
131
168
|
|
|
132
169
|
def tools_table # rubocop:disable Metrics/MethodLength
|
|
133
|
-
lines = [ "### All
|
|
170
|
+
lines = [ "### All 37 Tools", "" ]
|
|
134
171
|
|
|
135
172
|
if tool_mode == :cli
|
|
136
173
|
lines.concat(tools_table_cli)
|
|
@@ -145,11 +182,11 @@ module RailsAiContext
|
|
|
145
182
|
[
|
|
146
183
|
"| MCP | CLI | What it does |",
|
|
147
184
|
"|-----|-----|-------------|",
|
|
185
|
+
"| `rails_get_context(model:\"X\")` | `#{cli_cmd("context", "model=X")}` | **START HERE** — schema + model + controller + routes + views in one call |",
|
|
148
186
|
"| `rails_analyze_feature(feature:\"X\")` | `#{cli_cmd("analyze_feature", "feature=X")}` | Full-stack: models + controllers + routes + services + jobs + views + tests |",
|
|
149
|
-
"| `
|
|
150
|
-
"| `rails_search_code(pattern:\"X\", match_type:\"trace\")` | `#{cli_cmd("search_code", "pattern=X match_type=trace")}` | Trace: definition + source + siblings + callers + test coverage |",
|
|
187
|
+
"| `rails_search_code(pattern:\"X\", match_type:\"trace\")` | `#{cli_cmd("search_code", "pattern=X match_type=trace")}` | Search + trace: definition, source, callers, test coverage. Also: `match_type:\"any\"` for regex search |",
|
|
151
188
|
"| `rails_get_controllers(controller:\"X\", action:\"Y\")` | `#{cli_cmd("controllers", "controller=X action=Y")}` | Action source + inherited filters + render map + private methods |",
|
|
152
|
-
"| `rails_validate(files:[...], level:\"rails\")` | `#{cli_cmd("validate", "files=a.rb,b.rb level=rails")}` | Syntax + semantic validation
|
|
189
|
+
"| `rails_validate(files:[...], level:\"rails\")` | `#{cli_cmd("validate", "files=a.rb,b.rb level=rails")}` | Syntax + semantic validation (run after EVERY edit) |",
|
|
153
190
|
"| `rails_get_schema(table:\"X\")` | `#{cli_cmd("schema", "table=X")}` | Columns with [indexed]/[unique]/[encrypted]/[default] hints |",
|
|
154
191
|
"| `rails_get_model_details(model:\"X\")` | `#{cli_cmd("model_details", "model=X")}` | Associations, validations, scopes, enums, macros, delegations |",
|
|
155
192
|
"| `rails_get_routes(controller:\"X\")` | `#{cli_cmd("routes", "controller=X")}` | Routes with code-ready helpers and controller filters inline |",
|
|
@@ -160,7 +197,6 @@ module RailsAiContext
|
|
|
160
197
|
"| `rails_get_concern(name:\"X\", detail:\"full\")` | `#{cli_cmd("concern", "name=X detail=full")}` | Concern methods with source + which models include it |",
|
|
161
198
|
"| `rails_get_callbacks(model:\"X\")` | `#{cli_cmd("callbacks", "model=X")}` | Callbacks in Rails execution order with source |",
|
|
162
199
|
"| `rails_get_edit_context(file:\"X\", near:\"Y\")` | `#{cli_cmd("edit_context", "file=X near=Y")}` | Code around a match with class/method context |",
|
|
163
|
-
"| `rails_search_code(pattern:\"X\")` | `#{cli_cmd("search_code", "pattern=X")}` | Regex search + `exclude_tests` + `group_by_file` + pagination |",
|
|
164
200
|
"| `rails_get_service_pattern` | `#{cli_cmd("service_pattern")}` | Service objects: interface, dependencies, side effects, callers |",
|
|
165
201
|
"| `rails_get_job_pattern` | `#{cli_cmd("job_pattern")}` | Jobs: queue, retries, guard clauses, broadcasts, schedules |",
|
|
166
202
|
"| `rails_get_env` | `#{cli_cmd("env")}` | Environment variables + credentials keys (not values) |",
|
|
@@ -178,7 +214,11 @@ module RailsAiContext
|
|
|
178
214
|
"| `rails_get_frontend_stack` | `#{cli_cmd("frontend_stack")}` | React/Vue/Svelte/Angular, Inertia, TypeScript, package manager |",
|
|
179
215
|
"| `rails_search_docs(query:\"X\")` | `#{cli_cmd("search_docs", "query=X")}` | Bundled topic index with weighted keyword search, on-demand GitHub fetch |",
|
|
180
216
|
"| `rails_query(sql:\"X\")` | `#{cli_cmd("query", "sql=X")}` | Safe read-only SQL queries with timeout, row limit, column redaction |",
|
|
181
|
-
"| `rails_read_logs(level:\"X\")` | `#{cli_cmd("read_logs", "level=X")}` | Reverse file tail with level filtering and sensitive data redaction |"
|
|
217
|
+
"| `rails_read_logs(level:\"X\")` | `#{cli_cmd("read_logs", "level=X")}` | Reverse file tail with level filtering and sensitive data redaction |",
|
|
218
|
+
"| `rails_generate_test(model:\"X\")` | `#{cli_cmd("generate_test", "model=X")}` | Generate test scaffolding matching project patterns (framework, factories, style) |",
|
|
219
|
+
"| `rails_diagnose(error:\"X\")` | `#{cli_cmd("diagnose", "error=\"X\"")}` | One-call error diagnosis: context + git changes + logs + fix suggestions |",
|
|
220
|
+
"| `rails_review_changes(ref:\"main\")` | `#{cli_cmd("review_changes", "ref=main")}` | PR/commit review: file context + warnings (missing indexes, removed validations) |",
|
|
221
|
+
"| `rails_onboard(detail:\"standard\")` | `#{cli_cmd("onboard", "detail=standard")}` | Narrative app walkthrough for new developers or AI agents |"
|
|
182
222
|
]
|
|
183
223
|
end
|
|
184
224
|
|
|
@@ -186,11 +226,11 @@ module RailsAiContext
|
|
|
186
226
|
[
|
|
187
227
|
"| CLI | What it does |",
|
|
188
228
|
"|-----|-------------|",
|
|
229
|
+
"| `#{cli_cmd("context", "model=X")}` | **START HERE** — schema + model + controller + routes + views in one call |",
|
|
189
230
|
"| `#{cli_cmd("analyze_feature", "feature=X")}` | Full-stack: models + controllers + routes + services + jobs + views + tests |",
|
|
190
|
-
"| `#{cli_cmd("
|
|
191
|
-
"| `#{cli_cmd("search_code", "pattern=X match_type=trace")}` | Trace: definition + source + siblings + callers + test coverage |",
|
|
231
|
+
"| `#{cli_cmd("search_code", "pattern=X match_type=trace")}` | Search + trace: definition, source, callers, test coverage. Also: `match_type=any` for regex search |",
|
|
192
232
|
"| `#{cli_cmd("controllers", "controller=X action=Y")}` | Action source + inherited filters + render map + private methods |",
|
|
193
|
-
"| `#{cli_cmd("validate", "files=a.rb,b.rb level=rails")}` | Syntax + semantic validation
|
|
233
|
+
"| `#{cli_cmd("validate", "files=a.rb,b.rb level=rails")}` | Syntax + semantic validation (run after EVERY edit) |",
|
|
194
234
|
"| `#{cli_cmd("schema", "table=X")}` | Columns with [indexed]/[unique]/[encrypted]/[default] hints |",
|
|
195
235
|
"| `#{cli_cmd("model_details", "model=X")}` | Associations, validations, scopes, enums, macros, delegations |",
|
|
196
236
|
"| `#{cli_cmd("routes", "controller=X")}` | Routes with code-ready helpers and controller filters inline |",
|
|
@@ -201,7 +241,6 @@ module RailsAiContext
|
|
|
201
241
|
"| `#{cli_cmd("concern", "name=X detail=full")}` | Concern methods with source + which models include it |",
|
|
202
242
|
"| `#{cli_cmd("callbacks", "model=X")}` | Callbacks in Rails execution order with source |",
|
|
203
243
|
"| `#{cli_cmd("edit_context", "file=X near=Y")}` | Code around a match with class/method context |",
|
|
204
|
-
"| `#{cli_cmd("search_code", "pattern=X")}` | Regex search + `exclude_tests` + `group_by_file` + pagination |",
|
|
205
244
|
"| `#{cli_cmd("service_pattern")}` | Service objects: interface, dependencies, side effects, callers |",
|
|
206
245
|
"| `#{cli_cmd("job_pattern")}` | Jobs: queue, retries, guard clauses, broadcasts, schedules |",
|
|
207
246
|
"| `#{cli_cmd("env")}` | Environment variables + credentials keys (not values) |",
|
|
@@ -219,22 +258,65 @@ module RailsAiContext
|
|
|
219
258
|
"| `#{cli_cmd("frontend_stack")}` | React/Vue/Svelte/Angular, Inertia, TypeScript, package manager |",
|
|
220
259
|
"| `#{cli_cmd("search_docs", "query=X")}` | Bundled topic index with weighted keyword search, on-demand GitHub fetch |",
|
|
221
260
|
"| `#{cli_cmd("query", "sql=X")}` | Safe read-only SQL queries with timeout, row limit, column redaction |",
|
|
222
|
-
"| `#{cli_cmd("read_logs", "level=X")}` | Reverse file tail with level filtering and sensitive data redaction |"
|
|
261
|
+
"| `#{cli_cmd("read_logs", "level=X")}` | Reverse file tail with level filtering and sensitive data redaction |",
|
|
262
|
+
"| `#{cli_cmd("generate_test", "model=X")}` | Generate test scaffolding matching project patterns (framework, factories, style) |",
|
|
263
|
+
"| `#{cli_cmd("diagnose", "error=\"X\"")}` | One-call error diagnosis: context + git changes + logs + fix suggestions |",
|
|
264
|
+
"| `#{cli_cmd("review_changes", "ref=main")}` | PR/commit review: file context + warnings (missing indexes, removed validations) |",
|
|
265
|
+
"| `#{cli_cmd("onboard", "detail=standard")}` | Narrative app walkthrough for new developers or AI agents |"
|
|
223
266
|
]
|
|
224
267
|
end
|
|
225
268
|
|
|
226
|
-
# Full tool guide section — used by
|
|
269
|
+
# Full tool guide section — used by split rules files (.claude/rules/, .cursor/rules/, etc.)
|
|
227
270
|
def render_tools_guide
|
|
228
271
|
lines = []
|
|
229
272
|
lines << tools_header
|
|
230
273
|
lines << ""
|
|
231
274
|
lines.concat(tools_intro)
|
|
232
|
-
lines.concat(
|
|
275
|
+
lines.concat(tools_detail_guidance)
|
|
276
|
+
lines.concat(tools_power_tool_section)
|
|
277
|
+
lines.concat(tools_workflow_section)
|
|
278
|
+
lines.concat(tools_antipatterns_section)
|
|
233
279
|
lines.concat(tools_rules_section)
|
|
234
280
|
lines.concat(tools_table)
|
|
235
281
|
lines
|
|
236
282
|
end
|
|
237
283
|
|
|
284
|
+
# Compact tool guide for root files (CLAUDE.md, AGENTS.md) that have line limits.
|
|
285
|
+
# Includes power tools + workflows + rules + dense tool name list (no table).
|
|
286
|
+
def render_tools_guide_compact
|
|
287
|
+
lines = []
|
|
288
|
+
lines << tools_header
|
|
289
|
+
lines << ""
|
|
290
|
+
lines.concat(tools_intro)
|
|
291
|
+
lines.concat(tools_power_tool_section)
|
|
292
|
+
lines.concat(tools_workflow_section)
|
|
293
|
+
lines.concat(tools_rules_section)
|
|
294
|
+
lines.concat(tools_name_list)
|
|
295
|
+
lines
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# Dense one-line-per-tool listing — fits in compact mode without the table overhead
|
|
299
|
+
def tools_name_list
|
|
300
|
+
all_tools = %w[
|
|
301
|
+
rails_get_context rails_analyze_feature rails_search_code rails_get_controllers
|
|
302
|
+
rails_validate rails_get_schema rails_get_model_details rails_get_routes
|
|
303
|
+
rails_get_view rails_get_design_system rails_get_stimulus rails_get_test_info
|
|
304
|
+
rails_get_concern rails_get_callbacks rails_get_edit_context
|
|
305
|
+
rails_get_service_pattern rails_get_job_pattern rails_get_env
|
|
306
|
+
rails_get_partial_interface rails_get_turbo_map rails_get_helper_methods
|
|
307
|
+
rails_get_config rails_get_gems rails_get_conventions rails_security_scan
|
|
308
|
+
rails_get_component_catalog rails_performance_check rails_dependency_graph
|
|
309
|
+
rails_migration_advisor rails_get_frontend_stack rails_search_docs
|
|
310
|
+
rails_query rails_read_logs rails_generate_test rails_diagnose
|
|
311
|
+
rails_review_changes rails_onboard
|
|
312
|
+
]
|
|
313
|
+
[
|
|
314
|
+
"### All #{all_tools.size} tools",
|
|
315
|
+
"`#{all_tools.join('` `')}`",
|
|
316
|
+
""
|
|
317
|
+
]
|
|
318
|
+
end
|
|
319
|
+
|
|
238
320
|
private
|
|
239
321
|
|
|
240
322
|
# Generate zsh-safe CLI command: rails 'ai:tool[name]' params
|
|
@@ -243,6 +325,19 @@ module RailsAiContext
|
|
|
243
325
|
cmd += " #{params}" if params
|
|
244
326
|
cmd
|
|
245
327
|
end
|
|
328
|
+
|
|
329
|
+
# Inline tool call for workflow steps (shorter format).
|
|
330
|
+
# mcp_name is the full MCP tool name (e.g. "rails_validate", "rails_get_context").
|
|
331
|
+
def tool_call_inline(mcp_name, mcp_params, cli_short, cli_params)
|
|
332
|
+
case tool_mode
|
|
333
|
+
when :cli
|
|
334
|
+
"`#{cli_cmd(cli_short, cli_params)}`"
|
|
335
|
+
when :mcp
|
|
336
|
+
"`#{mcp_name}(#{mcp_params})` or `#{cli_cmd(cli_short, cli_params)}`"
|
|
337
|
+
else
|
|
338
|
+
"`#{mcp_name}(#{mcp_params})`"
|
|
339
|
+
end
|
|
340
|
+
end
|
|
246
341
|
end
|
|
247
342
|
end
|
|
248
343
|
end
|
|
@@ -41,7 +41,11 @@ module RailsAiContext
|
|
|
41
41
|
Tools::GetFrontendStack,
|
|
42
42
|
Tools::SearchDocs,
|
|
43
43
|
Tools::Query,
|
|
44
|
-
Tools::ReadLogs
|
|
44
|
+
Tools::ReadLogs,
|
|
45
|
+
Tools::GenerateTest,
|
|
46
|
+
Tools::Diagnose,
|
|
47
|
+
Tools::ReviewChanges,
|
|
48
|
+
Tools::Onboard
|
|
45
49
|
].freeze
|
|
46
50
|
|
|
47
51
|
def initialize(app, transport: :stdio)
|