coatepec 0.4.0 → 0.5.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 +27 -0
- data/README.md +51 -13
- data/exe/coatepec-worker +14 -0
- data/lib/coatepec/mcp.rb +7 -1
- data/lib/coatepec/version.rb +1 -1
- data/lib/coatepec/worker_manager.rb +4 -1
- metadata +16 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7cbcec579a7904ef50c8d8227036bbb0dd45f05bd664ffa2fceb2d210f5171be
|
|
4
|
+
data.tar.gz: 672092f99f2bfab2de7ad832572e6f16b5aeea8613860f0456fc81f7abaf25f4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f065ef0f83fbf5796d8e333326d9cf852a7322de12a12f77ece713df6cf00d29f167ea3ca2001830cb70e1e770a4533e3b111956390da1d0968c682cdeb8335a
|
|
7
|
+
data.tar.gz: 62d2d70afe6f5554c4e40fd83572384161f1819b228e65baa5c3a9c048716632e47c126356810e0c5aeb1e2ca1e9a79ed30fe0d10e97e773d6f1b6527a373d38
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.0
|
|
4
|
+
|
|
5
|
+
- **Breaking:** `mcp` is no longer a runtime dependency of the `coatepec`
|
|
6
|
+
gem -- it's a development dependency, since Coatepec is meant to be
|
|
7
|
+
installed once outside any Rails app's own bundle and pointed at the app
|
|
8
|
+
via `--root`, not added to the app's `Gemfile` (`Worker::Client` resolves
|
|
9
|
+
the worker's `RUBYLIB` from Coatepec's own installation regardless).
|
|
10
|
+
Anyone whose MCP config currently launches Coatepec with `bundle exec
|
|
11
|
+
coatepec` from inside a target app's bundle will hit a `LoadError` on
|
|
12
|
+
upgrade once that bundle no longer pulls in `mcp` transitively.
|
|
13
|
+
|
|
14
|
+
**Migration:** `gem install mcp` alongside `coatepec`, and change your MCP
|
|
15
|
+
client config to invoke `coatepec` directly rather than `bundle exec
|
|
16
|
+
coatepec` (drop the `coatepec` line from the target app's `Gemfile` too,
|
|
17
|
+
if present -- see the README Quickstart for the corrected install story).
|
|
18
|
+
|
|
19
|
+
## 0.4.1
|
|
20
|
+
|
|
21
|
+
- Fix `exe/coatepec-worker` booting against a target app whose locally
|
|
22
|
+
installed default-gem versions (e.g. `json`) differ from what its
|
|
23
|
+
`Gemfile.lock` pins: `require "bundler/setup"` now runs before
|
|
24
|
+
`require "coatepec"` itself, so Bundler can pin default gems before
|
|
25
|
+
Ruby auto-activates a newer locally installed version and locks it in
|
|
26
|
+
for the rest of the process. Previously this broke every coatepec call
|
|
27
|
+
against such an app with `already activated X, but your Gemfile
|
|
28
|
+
requires Y`.
|
|
29
|
+
|
|
3
30
|
## 0.4.0
|
|
4
31
|
|
|
5
32
|
- Add `enums` to `rails_model`'s output, sourced from ActiveRecord's own
|
data/README.md
CHANGED
|
@@ -6,26 +6,31 @@ console.
|
|
|
6
6
|
|
|
7
7
|
## Quickstart
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
group :development, :test do
|
|
12
|
-
gem "coatepec", require: false
|
|
13
|
-
end
|
|
14
|
-
```
|
|
9
|
+
Coatepec is installed once, outside of any Rails app's own bundle, and
|
|
10
|
+
points at the app via `--root`:
|
|
15
11
|
|
|
16
12
|
```bash
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
gem install coatepec mcp
|
|
14
|
+
coatepec --version
|
|
19
15
|
```
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
Do not add `coatepec` to the target app's `Gemfile`. `Worker::Client#spawn_worker`
|
|
18
|
+
resolves both the worker executable and its `RUBYLIB` from Coatepec's own
|
|
19
|
+
installation, not from the app's bundle -- so the worker gets Coatepec's
|
|
20
|
+
`lib` regardless of what the app's Gemfile says. Adding it there is not just
|
|
21
|
+
redundant, it's a version-skew hazard: Bundler would activate whatever
|
|
22
|
+
version is in the app's lockfile while Coatepec itself keeps running the
|
|
23
|
+
version on `RUBYLIB`, and a drift between the two surfaces as a confusing
|
|
24
|
+
"already activated" failure. The only thing Coatepec needs from the target
|
|
25
|
+
app is `railties`, which is definitionally present in any Rails app you'd
|
|
26
|
+
point it at. Host app footprint is zero: no Gemfile line, no lockfile
|
|
27
|
+
change, no dependency resolution.
|
|
23
28
|
|
|
24
29
|
With the [Claude Code CLI](https://docs.claude.com/en/docs/claude-code),
|
|
25
30
|
from the Rails app's own root:
|
|
26
31
|
|
|
27
32
|
```bash
|
|
28
|
-
claude mcp add coatepec --scope project --
|
|
33
|
+
claude mcp add coatepec --scope project -- coatepec --root .
|
|
29
34
|
```
|
|
30
35
|
|
|
31
36
|
That writes a project-scoped `.mcp.json` you can commit so the whole team
|
|
@@ -36,8 +41,8 @@ same thing looks like:
|
|
|
36
41
|
{
|
|
37
42
|
"mcpServers": {
|
|
38
43
|
"coatepec": {
|
|
39
|
-
"command": "
|
|
40
|
-
"args": ["
|
|
44
|
+
"command": "coatepec",
|
|
45
|
+
"args": ["--root", "."]
|
|
41
46
|
}
|
|
42
47
|
}
|
|
43
48
|
}
|
|
@@ -93,6 +98,29 @@ includes an `execution_mode` field (`fork`, `spawn_fallback`, or
|
|
|
93
98
|
call; `spawn_after_crash` results also carry the crashed fork's own stderr
|
|
94
99
|
under `crashed_fork_stderr` so the crash can be diagnosed.
|
|
95
100
|
|
|
101
|
+
`macos_fork: true` also effectively requires
|
|
102
|
+
`OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES` in Coatepec's own environment.
|
|
103
|
+
Without it, a forked child that touches an Objective-C-initialized class
|
|
104
|
+
aborts -- Coatepec retries via spawn, so it degrades silently to the slow
|
|
105
|
+
path (no crash, no error surfaced) rather than failing loudly, and you
|
|
106
|
+
simply never get the speedup. Set it on the MCP server process itself:
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"mcpServers": {
|
|
111
|
+
"coatepec": {
|
|
112
|
+
"command": "coatepec",
|
|
113
|
+
"args": ["--root", "."],
|
|
114
|
+
"env": { "OBJC_DISABLE_INITIALIZE_FORK_SAFETY": "YES" }
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Be aware this flag disables a real safety check in Apple's Objective-C
|
|
121
|
+
runtime; it's a reasonable trade for a local dev/test sidecar, but it's not
|
|
122
|
+
a no-op.
|
|
123
|
+
|
|
96
124
|
## Tools
|
|
97
125
|
|
|
98
126
|
| Tool | Input | Notes |
|
|
@@ -115,6 +143,16 @@ worker). For most apps this is invisible, but if you ever see behavior differ
|
|
|
115
143
|
between Coatepec and your own `bundle exec rspec`, this is the first thing to
|
|
116
144
|
suspect.
|
|
117
145
|
|
|
146
|
+
### Restarts
|
|
147
|
+
|
|
148
|
+
If any tool call fails with `sidecar_restart_required`, the target app's
|
|
149
|
+
`Gemfile`/`Gemfile.lock` changed since Coatepec's own parent process (the
|
|
150
|
+
"sidecar") started -- not just the warm test worker, which Coatepec restarts
|
|
151
|
+
on its own. This is expected any time you switch branches, pull, or rebase
|
|
152
|
+
across a commit that touches the Gemfile, since the sidecar is managed by
|
|
153
|
+
your MCP client rather than by Coatepec itself: restart your MCP client (or
|
|
154
|
+
however it manages the Coatepec process) to pick up the change.
|
|
155
|
+
|
|
118
156
|
## Security boundary
|
|
119
157
|
|
|
120
158
|
No eval, console, SQL/record access, shell, Rake, or file-write tool. Spec
|
data/exe/coatepec-worker
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
+
# Must run before any other require, including "coatepec" itself. Ruby
|
|
5
|
+
# auto-activates the newest installed version of a default gem (json,
|
|
6
|
+
# among others) the moment anything requires it, and a gem version can't
|
|
7
|
+
# be changed once activated -- so if that happens before Bundler pins
|
|
8
|
+
# versions to what the target app's Gemfile.lock actually specifies,
|
|
9
|
+
# Bundler.setup then fails with "already activated X, but your Gemfile
|
|
10
|
+
# requires Y" for any default gem that happens to have a newer version
|
|
11
|
+
# installed locally than what's locked. require "coatepec" below pulls in
|
|
12
|
+
# "json" (via protocol.rb) as its very first transitive require, so it's
|
|
13
|
+
# exactly the kind of require this has to run ahead of.
|
|
14
|
+
# Worker::Client#spawn_worker already sets BUNDLE_GEMFILE to the target
|
|
15
|
+
# app's Gemfile before this process starts.
|
|
16
|
+
require "bundler/setup"
|
|
17
|
+
|
|
4
18
|
require "coatepec"
|
|
5
19
|
|
|
6
20
|
# Preserve a real handle to the OS stdout fd for the private NDJSON
|
data/lib/coatepec/mcp.rb
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
begin
|
|
4
|
+
require "mcp"
|
|
5
|
+
rescue LoadError
|
|
6
|
+
raise LoadError, "The \"mcp\" gem is required to run Coatepec but is not installed. " \
|
|
7
|
+
"Install it alongside Coatepec: `gem install coatepec mcp`."
|
|
8
|
+
end
|
|
9
|
+
|
|
4
10
|
require "coatepec"
|
|
5
11
|
require_relative "mcp/response"
|
|
6
12
|
require_relative "mcp/tools"
|
data/lib/coatepec/version.rb
CHANGED
|
@@ -68,7 +68,10 @@ module Coatepec
|
|
|
68
68
|
reason = @change_detector.restart_reason(@snapshot)
|
|
69
69
|
case reason
|
|
70
70
|
when :sidecar_restart_required
|
|
71
|
-
raise Coatepec::Error.new(
|
|
71
|
+
raise Coatepec::Error.new(
|
|
72
|
+
:sidecar_restart_required,
|
|
73
|
+
"Gemfile changed; restart your MCP client to restart Coatepec and pick up the change"
|
|
74
|
+
)
|
|
72
75
|
when :worker_restart_required
|
|
73
76
|
restart_worker!
|
|
74
77
|
end
|
metadata
CHANGED
|
@@ -1,28 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: coatepec
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Enrique Mogollan
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-08-
|
|
10
|
+
date: 2026-08-05 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
-
- !ruby/object:Gem::Dependency
|
|
13
|
-
name: mcp
|
|
14
|
-
requirement: !ruby/object:Gem::Requirement
|
|
15
|
-
requirements:
|
|
16
|
-
- - "~>"
|
|
17
|
-
- !ruby/object:Gem::Version
|
|
18
|
-
version: '1.0'
|
|
19
|
-
type: :runtime
|
|
20
|
-
prerelease: false
|
|
21
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
-
requirements:
|
|
23
|
-
- - "~>"
|
|
24
|
-
- !ruby/object:Gem::Version
|
|
25
|
-
version: '1.0'
|
|
26
12
|
- !ruby/object:Gem::Dependency
|
|
27
13
|
name: railties
|
|
28
14
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -43,6 +29,20 @@ dependencies:
|
|
|
43
29
|
- - "<"
|
|
44
30
|
- !ruby/object:Gem::Version
|
|
45
31
|
version: '8.2'
|
|
32
|
+
- !ruby/object:Gem::Dependency
|
|
33
|
+
name: mcp
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
35
|
+
requirements:
|
|
36
|
+
- - "~>"
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: '1.0'
|
|
39
|
+
type: :development
|
|
40
|
+
prerelease: false
|
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
42
|
+
requirements:
|
|
43
|
+
- - "~>"
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '1.0'
|
|
46
46
|
description: Coatepec is a local stdio MCP sidecar that keeps an isolated Rails test
|
|
47
47
|
worker warm so coding agents can run targeted RSpec examples quickly, without exposing
|
|
48
48
|
a general Rails console.
|