rails_mind 0.1.0 → 0.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/CONTRIBUTING.md +4 -4
- data/README.md +15 -4
- data/docs/agents.md +212 -0
- data/docs/compatibility.md +48 -2
- data/docs/sdk.md +133 -9
- data/lib/generators/rails_mind/agent/agent_generator.rb +155 -0
- data/lib/generators/rails_mind/agent/templates/headers.rb.tt +6 -0
- data/lib/generators/rails_mind/install/install_generator.rb +4 -0
- data/lib/generators/rails_mind/install/templates/initializer.rb.tt +3 -0
- data/lib/rails_mind/agent_headers.rb +62 -0
- data/lib/rails_mind/client.rb +1 -4
- data/lib/rails_mind/collector.rb +72 -26
- data/lib/rails_mind/configuration.rb +3 -1
- data/lib/rails_mind/context.rb +21 -0
- data/lib/rails_mind/diagnostic.rb +3 -2
- data/lib/rails_mind/integrations/action_mailer.rb +195 -0
- data/lib/rails_mind/integrations/rails.rb +90 -24
- data/lib/rails_mind/railtie.rb +9 -0
- data/lib/rails_mind/sampling.rb +211 -0
- data/lib/rails_mind/transport.rb +44 -6
- data/lib/rails_mind/version.rb +1 -1
- data/lib/rails_mind.rb +1 -0
- metadata +8 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 819a570e3f4f65e0fb8bae7de68b1a81ee744bccb77349858c640fcc912e95b4
|
|
4
|
+
data.tar.gz: 62df4fca70603e28458d277dcd8d734a5de04af7c514f997e15686122a02dbd2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3583084684b6ac4b165864c14fbfe3922fc2f678c8d7aa9383418d95fdc528083bbe2327e5428d167d80e54a28445309eb6243bd3c6c3dac36fc8a67fa9e0630
|
|
7
|
+
data.tar.gz: e968233e4025ce470a83207214ef886032bff662faea00f824f3aceefad55319aa6d3235b62cc16368c5b8ccec7db86a6914ce1d5cb1a5db2c9bb282a543f0f2
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0 — 2026-10-10
|
|
4
|
+
|
|
5
|
+
- Enable bounded automatic endpoint sampling for routine successful requests, driven by expiring hosted policies. Preserve slow, failed, repeated-query requests and all other signal kinds from SDK sampling.
|
|
6
|
+
- Report eligible request selection and queue losses with immutable IDs and independent acknowledgments, including report-only batches at zero sampling rates. Keep old-server event delivery compatible until a v1 handshake.
|
|
7
|
+
- Add explicit local opt-out, effective request metadata, bounded control parsing, fork resets, and sampling diagnostics. Local opt-out does not disable server-side sampling or quotas.
|
|
8
|
+
- Separate known local drops from unconfirmed delivery; failed responses may follow partial server acceptance.
|
|
9
|
+
|
|
10
|
+
## 0.2.0 — 2026-10-09
|
|
11
|
+
|
|
12
|
+
- Correlate requests, serialized ActiveJob executions, and mailer attempts with native trace IDs while preserving existing OpenTelemetry context.
|
|
13
|
+
- Observe job enqueue/start, retry/discard, and completion without changing existing job-count semantics; distinguish total queue delay from delay after a scheduled job becomes eligible.
|
|
14
|
+
- Observe Action Mailer processing, ordinary/forced delivery attempts, disabled delivery, callback aborts, and exposed failures. Collect only bounded lifecycle metadata, excluding recipients, subjects, message bodies, attachments, and arguments. Recipient delivery remains unknown.
|
|
15
|
+
- Connect Claude Code and Codex with `rails_mind:agent`, including a write-free preview, preserved existing configuration, and shared agent instructions.
|
|
16
|
+
- Choose an environment-variable API token or a local Rails encrypted-credentials helper; check readiness without displaying the token.
|
|
17
|
+
- Document the full agent handoff: read findings, follow a brief, report a PR, and watch deployment and recurrence in RailsMind.
|
|
18
|
+
|
|
3
19
|
## 0.1.0 — 2026-09-25
|
|
4
20
|
|
|
5
21
|
Initial public release of the RailsMind client under the MIT license.
|
data/CONTRIBUTING.md
CHANGED
|
@@ -6,7 +6,7 @@ sample are maintained separately and remain proprietary.
|
|
|
6
6
|
|
|
7
7
|
## Setup
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
CI uses Ruby 4.0.6 and Node 22. Native workflow tests have also been run locally on Ruby 4.0.7; use the committed lockfile.
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
12
|
git clone https://github.com/cmartyn/rails_mind.git
|
|
@@ -37,7 +37,7 @@ read this public repository.
|
|
|
37
37
|
## Packaging and releases
|
|
38
38
|
|
|
39
39
|
`bundle exec ruby script/package_smoke.rb` builds a temporary gem and exercises its
|
|
40
|
-
packaged installer and
|
|
40
|
+
packaged installer, browser files, and native workflow integrations. `bundle exec rake build` writes the gem to
|
|
41
41
|
`pkg/`. Neither command publishes anything.
|
|
42
42
|
|
|
43
43
|
Publishing uses [RubyGems trusted publishing](https://guides.rubygems.org/trusted-publishing/)
|
|
@@ -66,8 +66,8 @@ customer application.
|
|
|
66
66
|
Create an annotated tag matching the gem version and push it:
|
|
67
67
|
|
|
68
68
|
```sh
|
|
69
|
-
git tag -a v0.
|
|
70
|
-
git push origin v0.
|
|
69
|
+
git tag -a v0.2.0 -m "Release rails_mind 0.2.0"
|
|
70
|
+
git push origin v0.2.0
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
The workflow verifies the tag/version, reruns the Ruby, JavaScript, and package
|
data/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# RailsMind SDK
|
|
2
2
|
|
|
3
3
|
The MIT-licensed Ruby client for [RailsMind](https://railsmind.com). One bounded
|
|
4
|
-
collector for Rails requests, errors, jobs, Ahoy events, Flipper
|
|
5
|
-
and selected OpenTelemetry spans. Version 0.
|
|
4
|
+
collector for Rails requests, errors, jobs, mailer attempts, Ahoy events, Flipper
|
|
5
|
+
observations, and selected OpenTelemetry spans. Version 0.3.0 is an early release; see
|
|
6
6
|
[compatibility and validation limits](docs/compatibility.md).
|
|
7
7
|
|
|
8
8
|
```ruby
|
|
9
|
-
gem "rails_mind", "~> 0.
|
|
9
|
+
gem "rails_mind", "~> 0.3.0"
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
Install from RubyGems.org and commit your application's `Gemfile.lock` to pin the
|
|
@@ -44,8 +44,19 @@ RailsMind.with_context(user_id: current_user.id.to_s, account_id: current_accoun
|
|
|
44
44
|
end
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
Requests, ActiveJob executions, and Action Mailer attempts share native trace
|
|
48
|
+
context without requiring OpenTelemetry. Existing OpenTelemetry context stays
|
|
49
|
+
authoritative. Mail observations contain class/action, timing, and attempt
|
|
50
|
+
metadata, never recipients or rendered content; an attempt is not proof of inbox
|
|
51
|
+
delivery. See [workflow observations](docs/sdk.md#jobs-and-mailer-workflows).
|
|
52
|
+
|
|
47
53
|
See [installation and privacy](docs/sdk.md) and [compatibility](docs/compatibility.md).
|
|
48
54
|
|
|
55
|
+
Connect Claude Code or Codex with `bin/rails generate rails_mind:agent --plan`.
|
|
56
|
+
Choose an environment-variable API token or Rails encrypted credentials, then
|
|
57
|
+
follow the [agent setup guide](docs/agents.md) from first connection to a reported
|
|
58
|
+
PR and deployment confirmation. Requires rails_mind 0.2.0 or later.
|
|
59
|
+
|
|
49
60
|
Tests:
|
|
50
61
|
|
|
51
62
|
```sh
|
|
@@ -56,4 +67,4 @@ bundle exec ruby script/package_smoke.rb
|
|
|
56
67
|
ruby script_benchmark.rb
|
|
57
68
|
```
|
|
58
69
|
|
|
59
|
-
Business/
|
|
70
|
+
Automatic endpoint sampling is enabled by default. The hosted policy can reduce routine successful requests while preserving failed, slow, or repeated-query requests and all other signal kinds from sampling. Business/error events remain unsampled; bounded queues and delivery are still best effort. See [sampling and coverage](docs/sdk.md#automatic-endpoint-sampling) and inspect `RailsMind.stats`. Use a transactional outbox when durable business-event delivery is required.
|
data/docs/agents.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# Bring your agent aboard
|
|
2
|
+
|
|
3
|
+
RailsMind watches your Rails app. Your coding agent works in the repository you
|
|
4
|
+
already use. Connect them once, then move from a finding to a reviewed fix without
|
|
5
|
+
copying evidence between windows.
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
RailsMind spots a problem → your agent proposes a PR → you review and ship
|
|
9
|
+
↓
|
|
10
|
+
RailsMind watches the deployed fix
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Available in rails_mind 0.2.0. The hosted service must support `report_fix` before
|
|
14
|
+
agents can report PRs. Setup is deterministic: it makes no model calls, starts no
|
|
15
|
+
investigation, and does not merge or deploy anything.
|
|
16
|
+
|
|
17
|
+
## 1. Preview the agent link
|
|
18
|
+
|
|
19
|
+
From your Rails application's checkout:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
bin/rails generate rails_mind:agent --plan
|
|
23
|
+
bin/rails generate rails_mind:agent
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
You'll see three stages:
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
RailsMind · Agent link
|
|
30
|
+
1 / 3 · Configure the connection (env)
|
|
31
|
+
2 / 3 · Give your agent the flight plan
|
|
32
|
+
3 / 3 · Awaiting your signal
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The first command writes nothing. The second adds a Claude Code `.mcp.json` entry
|
|
36
|
+
and a marked RailsMind section in `AGENTS.md`. When an existing `CLAUDE.md` needs
|
|
37
|
+
an import, it adds one with the correct relative path. Codex configuration is
|
|
38
|
+
printed for you to review and add; the installer never changes global settings.
|
|
39
|
+
Other MCP servers and existing RailsMind entries are preserved, even with
|
|
40
|
+
`--force`. A skipped entry means you may need the proposed manual change shown
|
|
41
|
+
in the output. Review the diff before committing it.
|
|
42
|
+
|
|
43
|
+
The installer uses `https://railsmind.com`; `RAILS_MIND_ENDPOINT` can select another
|
|
44
|
+
hosted installation. It does not create a local MCP server.
|
|
45
|
+
|
|
46
|
+
## 2. Choose where the API token lives
|
|
47
|
+
|
|
48
|
+
Create a **read,write API token** under RailsMind **Settings → API tokens**. An
|
|
49
|
+
owner or admin creates it; it acts with that person's current organization role.
|
|
50
|
+
A read-only token can explore findings but cannot report fixes. Tokens can be
|
|
51
|
+
revoked on the same page.
|
|
52
|
+
|
|
53
|
+
`RAILS_MIND_KEY` is your environment's **telemetry ingestion key**. It cannot read
|
|
54
|
+
findings or authenticate an agent. The agent uses a separate `rmt_…` API token.
|
|
55
|
+
|
|
56
|
+
### Environment variable (default)
|
|
57
|
+
|
|
58
|
+
Make `RAILSMIND_API_TOKEN` available to the process running your agent. Keep the
|
|
59
|
+
real value in your local secret settings, outside version control. For Claude
|
|
60
|
+
Code GUI/IDE sessions, its user settings support an `env` entry; a shell export
|
|
61
|
+
alone may not reach an app opened from the desktop.
|
|
62
|
+
|
|
63
|
+
The generated `.mcp.json` contains a variable reference, never the value. A
|
|
64
|
+
project entry can take precedence over an existing user-level entry, so prepare
|
|
65
|
+
the variable before enabling it.
|
|
66
|
+
|
|
67
|
+
For local Codex CLI, IDE and desktop sessions, add the printed configuration to
|
|
68
|
+
`~/.codex/config.toml` (or `$CODEX_HOME/config.toml`):
|
|
69
|
+
|
|
70
|
+
```toml
|
|
71
|
+
[mcp_servers.railsmind]
|
|
72
|
+
url = "https://railsmind.com/mcp"
|
|
73
|
+
bearer_token_env_var = "RAILSMIND_API_TOKEN"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
This one entry can serve multiple repositories in the same RailsMind organization.
|
|
77
|
+
|
|
78
|
+
### Rails encrypted credentials
|
|
79
|
+
|
|
80
|
+
Prefer to keep this app's API token with its other Rails secrets?
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
bin/rails generate rails_mind:agent --auth=credentials --plan
|
|
84
|
+
bin/rails generate rails_mind:agent --auth=credentials
|
|
85
|
+
bin/rails credentials:edit --environment development
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Add through the credentials editor:
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
rails_mind:
|
|
92
|
+
api_token: rmt_your_token_here
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The encrypted file can be committed. Its matching decryption key must remain
|
|
96
|
+
local and ignored by Git. Anyone able to decrypt this credential set can use the
|
|
97
|
+
saved token; choose personal environment-variable tokens when each developer
|
|
98
|
+
needs separate attribution or revocation.
|
|
99
|
+
|
|
100
|
+
Credentials mode generates `bin/rails_mind_mcp_headers`. Claude Code's
|
|
101
|
+
`headersHelper` and Codex's `http_headers_helper` call it to obtain authentication
|
|
102
|
+
headers at connection time. Ruby and the installed bundle must be available to
|
|
103
|
+
the agent. No Rails application boot, database connection or telemetry collection
|
|
104
|
+
is needed. Run this safe readiness check:
|
|
105
|
+
|
|
106
|
+
```sh
|
|
107
|
+
bin/rails_mind_mcp_headers --environment development --check
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
It reports readiness without printing the token, and does **not** test network
|
|
111
|
+
access. Without `--check`, stdout contains secret-bearing headers intended only
|
|
112
|
+
for the MCP client. Never paste that output into a chat or issue.
|
|
113
|
+
|
|
114
|
+
By default the helper selects development credentials, falling back to the shared
|
|
115
|
+
Rails credentials file with Rails' normal key-file selection. Choose another
|
|
116
|
+
local credential environment with `--credentials-environment=NAME` on the
|
|
117
|
+
generator. This is separate from the production environment you inspect in
|
|
118
|
+
RailsMind. Initializer-defined custom credential paths are not discovered because
|
|
119
|
+
the app is not booted; pass `--content-path PATH --key-path PATH` in both agents'
|
|
120
|
+
helper commands if needed. Relative paths resolve against the application root.
|
|
121
|
+
|
|
122
|
+
A nonblank `RAILSMIND_API_TOKEN` overrides credentials **when the helper receives
|
|
123
|
+
it**. Claude project helpers may remove credential-named environment variables,
|
|
124
|
+
including that token and `RAILS_MASTER_KEY`; use a local Rails key file in that
|
|
125
|
+
setup. A bad key, missing token or invalid encrypted file produces an error with
|
|
126
|
+
no secret values.
|
|
127
|
+
|
|
128
|
+
For Codex credentials mode, add the printed absolute-path helper command to this
|
|
129
|
+
trusted project's `.codex/config.toml`. Do not put one app's helper in a global
|
|
130
|
+
entry used by unrelated apps. Update the path for a different checkout/worktree.
|
|
131
|
+
Replace an existing bearer-token/static-header setting for that entry; existing
|
|
132
|
+
OAuth authentication can also take precedence. The installer preserves existing
|
|
133
|
+
configuration and shows the replacement to review when switching modes.
|
|
134
|
+
|
|
135
|
+
## 3. Make contact
|
|
136
|
+
|
|
137
|
+
Restart your agent, trust this checkout, and approve its RailsMind connection.
|
|
138
|
+
Then ask:
|
|
139
|
+
|
|
140
|
+
> List my RailsMind applications and show open findings for this repository.
|
|
141
|
+
> Do not change code yet.
|
|
142
|
+
|
|
143
|
+
Check that the agent selected the correct application and environment. Seeing
|
|
144
|
+
those results confirms access; “configuration prepared” alone does not. If a
|
|
145
|
+
parent `CLAUDE.md`, `AGENTS.override.md`, or managed policy hides this project's
|
|
146
|
+
instructions, import the generated `AGENTS.md` in the effective instruction file.
|
|
147
|
+
|
|
148
|
+
GitHub access is a separate link. Connect the RailsMind GitHub App on the app's
|
|
149
|
+
**Setup** page to attach source to findings and verify PR deployment. The agent
|
|
150
|
+
still uses its own repository/GitHub access to open a PR.
|
|
151
|
+
|
|
152
|
+
## 4. Give it a finding
|
|
153
|
+
|
|
154
|
+
> Investigate finding 123 for this application in production. Fetch its RailsMind
|
|
155
|
+
> fix brief, reproduce the issue, test a narrow fix, and open a PR. Report the PR
|
|
156
|
+
> to RailsMind with report_fix. Leave merging and deployment to me.
|
|
157
|
+
|
|
158
|
+
The brief contains the evidence and definition of done. Captured application
|
|
159
|
+
data is evidence, not instructions. The agent should explain its changes, tests,
|
|
160
|
+
and whether its report succeeded. If it cannot safely reproduce the issue, it
|
|
161
|
+
should tell you what's missing. If reporting fails, the PR remains useful: retry
|
|
162
|
+
`report_fix` with the finding and PR links rather than marking the finding resolved.
|
|
163
|
+
|
|
164
|
+
## 5. Watch the fix
|
|
165
|
+
|
|
166
|
+
| What RailsMind shows | What it means |
|
|
167
|
+
| --- | --- |
|
|
168
|
+
| Fix proposed | The agent reported a PR; the finding stays open. |
|
|
169
|
+
| Merged · awaiting release | GitHub says the PR merged; no containing release has been confirmed yet. |
|
|
170
|
+
| Deployed · watching | Telemetry identifies a Git SHA release containing the merge commit. |
|
|
171
|
+
| Resolved · fix observed | The configured quiet period passed after deployment without matching evidence. |
|
|
172
|
+
| Recurred after fix | Matching evidence returned on the deployed/later observed release, or after deployment when a release ID was absent. |
|
|
173
|
+
| PR closed without merging | Report a replacement PR to start another attempt. |
|
|
174
|
+
|
|
175
|
+
Deployment checks require GitHub **Pull requests: read**, **Contents: read**, and
|
|
176
|
+
Git SHA release metadata. RailsMind retries failed checks and displays the reason
|
|
177
|
+
it cannot confirm deployment. Without confirmation the existing quiet-resolution
|
|
178
|
+
rule can still close a finding as **quiet**, which is distinct from **fixed**.
|
|
179
|
+
Quiet telemetry is not proof that every affected path ran; SDK delivery is best
|
|
180
|
+
effort. Release-regression recurrence tracking is not included in this version.
|
|
181
|
+
Reporting the same PR again updates the note without erasing progress. A different
|
|
182
|
+
PR replaces the current attempt. RailsMind does not merge or deploy it.
|
|
183
|
+
|
|
184
|
+
## When a link needs attention
|
|
185
|
+
|
|
186
|
+
| Symptom | Next step |
|
|
187
|
+
| --- | --- |
|
|
188
|
+
| Server absent | Restart the agent; check project trust, config placement and organization MCP policy. |
|
|
189
|
+
| Missing variable or 401 | Set the API token in the agent process, check revocation and restart. Check whether a project entry overrides an older working entry. |
|
|
190
|
+
| Credential check fails | Confirm the selected file, matching local key and `rails_mind.api_token`. Use `--check`, never paste header output. |
|
|
191
|
+
| Ruby/Bundler not found | Make the app's Ruby and installed bundle available in the agent runtime. |
|
|
192
|
+
| Reads work, report is forbidden | Use read,write scope and a contributing organization role. |
|
|
193
|
+
| report_fix is unknown | The hosted RailsMind deployment needs the agent-loop update. Keep the PR and report it after that update. |
|
|
194
|
+
| PR reported but deployment pending | Check the finding's reason, GitHub permissions, merge state, and release SHA detection. |
|
|
195
|
+
| Another checkout fails | Correct the helper's absolute path and provide that checkout's ignored key file. |
|
|
196
|
+
|
|
197
|
+
## Supported surfaces and verification limits
|
|
198
|
+
|
|
199
|
+
This integration targets local Claude Code and Codex CLI, IDE and desktop
|
|
200
|
+
sessions using their documented HTTP MCP configurations. Helper configuration
|
|
201
|
+
requires a client version that supports it; use environment-variable mode if it
|
|
202
|
+
doesn't. Neither the local generator nor passing unit tests certifies a particular
|
|
203
|
+
agent installation. Verify the read-only “Make contact” step in each setup.
|
|
204
|
+
|
|
205
|
+
Hosted/cloud and remote executor sessions do not automatically inherit local
|
|
206
|
+
config, Ruby, credentials or keys. Codex documents helpers only for local HTTP
|
|
207
|
+
connections. Use the hosted surface's supported connector/authentication setup;
|
|
208
|
+
do not upload a production Rails decryption key just to make an agent connection.
|
|
209
|
+
|
|
210
|
+
References: [Claude Code MCP](https://code.claude.com/docs/en/mcp),
|
|
211
|
+
[Codex MCP](https://learn.chatgpt.com/docs/extend/mcp), and
|
|
212
|
+
[Rails credentials](https://guides.rubyonrails.org/security.html#custom-credentials).
|
data/docs/compatibility.md
CHANGED
|
@@ -38,9 +38,9 @@ node --test javascript/rails_mind.test.js
|
|
|
38
38
|
bundle exec ruby script/package_smoke.rb
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
CI runs Ruby 4.0.6 / Rails 8.1.
|
|
41
|
+
CI runs Ruby 4.0.6 / the locked Rails 8.1.4 dependencies on Linux, plus browser adapter contract tests
|
|
42
42
|
on Node 22. The package smoke check builds and installs a gem in a temporary directory, loads that copy,
|
|
43
|
-
and runs the installer against its packaged
|
|
43
|
+
and runs the installer and native workflow tests against its packaged files.
|
|
44
44
|
The sample app remains in the hosted application's repository with its own lockfile.
|
|
45
45
|
|
|
46
46
|
## 0.1.0 release verification
|
|
@@ -64,3 +64,49 @@ and Node 22:
|
|
|
64
64
|
These checks cover the client package and its documented integrations locally.
|
|
65
65
|
They do not certify other browsers, every allowed Ruby/Rails combination,
|
|
66
66
|
production delivery guarantees, or a deployed customer application's setup.
|
|
67
|
+
|
|
68
|
+
## 0.2.0 agent setup verification
|
|
69
|
+
|
|
70
|
+
The agent generator and encrypted-credentials helper are tested with Ruby 4.0.7
|
|
71
|
+
and Rails/Active Support 8.1.3.1. Tests cover preview/repeatability, preservation of
|
|
72
|
+
existing MCP and instruction files, shared and environment-specific credentials,
|
|
73
|
+
custom paths, safe diagnostics, environment-variable precedence, and packaged
|
|
74
|
+
files. The helper loads Active Support without initializing the application.
|
|
75
|
+
|
|
76
|
+
Client configuration uses the documented Claude Code `headersHelper` and Codex
|
|
77
|
+
`http_headers_helper` interfaces. These tests do not certify every desktop, IDE,
|
|
78
|
+
cloud or older client version; verify read access in your agent after setup. See
|
|
79
|
+
[agent setup and limitations](agents.md#supported-surfaces-and-verification-limits).
|
|
80
|
+
|
|
81
|
+
## 0.2.0 workflow observation verification
|
|
82
|
+
|
|
83
|
+
The native context, ActiveJob, and Action Mailer tests run with Ruby 4.0.7,
|
|
84
|
+
Rails/ActiveJob/ActionMailer 8.1.4, and Mail 2.9.1. They cover serialized jobs,
|
|
85
|
+
retries/discards, enqueue aborts/errors, schedule-aware delay, context restoration,
|
|
86
|
+
ordinary/forced mail, disabled transport, hidden/raised transport errors, callback
|
|
87
|
+
aborts/failures, lazy rendering, repeated attempts, existing OpenTelemetry, and
|
|
88
|
+
collector failures. Auxiliary mail sent inside callbacks does not inherit the
|
|
89
|
+
forced ActionMailer attempt. Tests use an in-memory collector and test/failing
|
|
90
|
+
transports; they do not send external email.
|
|
91
|
+
|
|
92
|
+
Older gem-permitted Rails versions remain uncertified. Provider acceptance,
|
|
93
|
+
recipient inbox delivery, direct backend jobs, direct provider HTTP sends, and
|
|
94
|
+
durable workflow completeness are outside this contract. Validate the released
|
|
95
|
+
SDK against your app's queue, callback ordering, and delivery adapter. The hosted
|
|
96
|
+
service exposes bounded workflow metadata and leaves recipient delivery unknown.
|
|
97
|
+
|
|
98
|
+
## 0.3.0 endpoint sampling verification
|
|
99
|
+
|
|
100
|
+
The Ruby suite passes locally with Ruby 4.0.7 and the locked Rails 8.1.4
|
|
101
|
+
libraries: 105 tests and 1,311 assertions, with no failures or skips. The three
|
|
102
|
+
Node browser-adapter contract tests also pass. These are isolated SDK/library
|
|
103
|
+
tests; they do not boot a Rails application or use a database. CI separately
|
|
104
|
+
runs the packaged-gem installation smoke check on Ruby 4.0.6.
|
|
105
|
+
|
|
106
|
+
Coverage includes protected signals, deterministic shared selection, endpoint
|
|
107
|
+
rates, local opt-out, malformed/expired controls, monotonic expiry, queue loss,
|
|
108
|
+
immutable reports and acknowledgments, quota-response retries, old-server
|
|
109
|
+
fallback, idle zero-rate report refresh, streamed response bounds, batch byte
|
|
110
|
+
limits, and real process fork resets. Fake transports verify the wire contract;
|
|
111
|
+
deployed server policy behavior, cross-process traffic forecasts, and a
|
|
112
|
+
customer app's production overhead require hosted/staging validation.
|
data/docs/sdk.md
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
The gem is `rails_mind`, namespace `RailsMind`. Install the MIT-licensed client
|
|
4
4
|
from RubyGems.org and commit the application lockfile to retain the selected
|
|
5
5
|
version. The hosted RailsMind service is a separate, proprietary application.
|
|
6
|
-
Version 0.
|
|
6
|
+
Version 0.3.0 is an early release with the [documented compatibility limits](compatibility.md).
|
|
7
7
|
|
|
8
8
|
## Install
|
|
9
9
|
|
|
10
10
|
```ruby
|
|
11
11
|
# Customer Gemfile
|
|
12
|
-
gem "rails_mind", "~> 0.
|
|
12
|
+
gem "rails_mind", "~> 0.3.0"
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
```sh
|
|
@@ -131,7 +131,7 @@ RailsMind.capture_exception(error, handled: true)
|
|
|
131
131
|
|
|
132
132
|
Context is fiber-local and restored around requests/jobs. `identify` replaces the three identity values, so call it with all available values; passing nil clears that value. Preserve Ahoy's visitor ID when a visitor logs in, and emit `$identify` through Ahoy authentication to connect later events. Account IDs represent the current tenant, never a guessed company from email. Logout/account switching must update identity; a new request starts clean. Historical anonymous events are not rewritten or merged across accounts by the SDK.
|
|
133
133
|
|
|
134
|
-
ActiveJob serializes only the context identifier allowlist under `rails_mind_context`, then restores it while executing. Arguments are not inspected. This covers GoodJob through ActiveJob; direct Sidekiq jobs require a future explicit integration.
|
|
134
|
+
ActiveJob serializes only the context identifier allowlist under `rails_mind_context`, then restores it while executing. Arguments are not inspected. This covers GoodJob through ActiveJob; direct Sidekiq jobs require a future explicit integration. Without OpenTelemetry, RailsMind creates a trace ID at a request, job, or mailer boundary and carries it across serialized ActiveJob context. An active OpenTelemetry span remains authoritative. Native IDs correlate observations; they do not invent a distributed parent/child span tree. Cross-service propagation belongs to the existing OpenTelemetry library; choose ActiveJob `propagation_style: :child` for a linked trace tree when configuring a new provider.
|
|
135
135
|
|
|
136
136
|
## Ahoy
|
|
137
137
|
|
|
@@ -180,9 +180,124 @@ RailsMind::Integrations::OpenTelemetry.attach!
|
|
|
180
180
|
|
|
181
181
|
Attachment adds one idempotent processor; it does not replace the global provider, sampler, propagator, instrumentation, or other exporters. Its exporter only sanitizes and enqueues locally; the shared worker performs network I/O. Span context is attached at start so identity survives later export. Known safe attributes are allowlisted. Raw span names, exception span events, HTTP bodies/headers, SQL statements, and bind values are not exported to RailsMind. Existing third-party exporters retain their own behavior and privacy settings. [OpenTelemetry exporters](https://opentelemetry.io/docs/languages/ruby/exporters/).
|
|
182
182
|
|
|
183
|
-
Request
|
|
183
|
+
Request measurements and error reports come independently from Rails notifications/error reporting, even when detailed traces are sampled out. Routine requests separately follow the automatic endpoint sampling policy described below. Request measurements cover controller actions, not assets/health checks rejected before ActionController or streaming-body completion. Repeated-query evidence contains only normalized-query hashes and counts; it is a suspicion, not proof of an N+1. Hash normalization handles common literals, not every SQL grammar. Use Bullet/Prosopite or an explicit query-bound test in development to verify fixes. No production object scans are installed.
|
|
184
|
+
|
|
185
|
+
Full metrics/logs SDK integration is deferred. Hosted request aggregates describe retained events; sampling can bias their distributions. The SDK does not capture application logs.
|
|
186
|
+
|
|
187
|
+
## Automatic endpoint sampling
|
|
188
|
+
|
|
189
|
+
Version 0.3.0 enables automatic endpoint sampling by default. A compatible hosted
|
|
190
|
+
service supplies environment-wide endpoint rates based on its allowance policy.
|
|
191
|
+
The SDK applies them before queueing, reducing serialization, network, and retained
|
|
192
|
+
event volume. Each process uses the same policy and deterministic event-ID hash;
|
|
193
|
+
there are no independent per-process allowance grants. A server-side tightening
|
|
194
|
+
uses the same selection rule, so the two samplers do not multiply probabilities.
|
|
195
|
+
|
|
196
|
+
Only completed `request` events with status 200–399, a finite duration from zero
|
|
197
|
+
to below 1,000 ms, and fewer than three repeated queries are eligible. Slow,
|
|
198
|
+
failed, unknown-duration, and repeated-query requests remain unsampled, as do
|
|
199
|
+
business events, errors, jobs, mailer observations, visits, flags, checks, and
|
|
200
|
+
OpenTelemetry spans. This preserves their sampling priority, not guaranteed
|
|
201
|
+
delivery: queue bounds, payload limits, outages, and the server's hard daily quota
|
|
202
|
+
still apply. Existing OpenTelemetry samplers remain authoritative; this feature
|
|
203
|
+
does not promise complete distributed traces.
|
|
204
|
+
|
|
205
|
+
To turn off SDK request selection explicitly:
|
|
206
|
+
|
|
207
|
+
```ruby
|
|
208
|
+
RailsMind.configure do |config|
|
|
209
|
+
config.automatic_sampling = false
|
|
210
|
+
end
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The SDK communicates this choice on policy and ingestion requests. The
|
|
214
|
+
environment owner's hosted setting separately controls server-side sampling;
|
|
215
|
+
local opt-out does **not** disable it or bypass the daily quota.
|
|
216
|
+
|
|
217
|
+
The background worker requests `/api/v1/sampling_policy` with the ingest key and
|
|
218
|
+
refreshes at most once per minute after its first request observation, including
|
|
219
|
+
when the current rate is zero. It also receives controls on successful ingestion
|
|
220
|
+
and quota responses. Missing, malformed, or expired policies fall back to rate 1;
|
|
221
|
+
this may exhaust the server allowance during an outage. Expiry uses wall and
|
|
222
|
+
monotonic clocks, with a maximum accepted lifetime of ten minutes. Before a valid
|
|
223
|
+
v1 handshake, old servers and custom transports receive ordinary event-only
|
|
224
|
+
batches and retain normal flush behavior. Forked workers reset queues, policies,
|
|
225
|
+
counters, and report IDs and fetch their own copy of the shared policy.
|
|
226
|
+
|
|
227
|
+
Retained request properties include SDK-owned `rails_mind_sampling` metadata:
|
|
228
|
+
`version`, `policy_id`, effective `rate`, and `state` (`active`, `unavailable`,
|
|
229
|
+
`expired`, `disabled`, or `protected`). This is the SDK selection decision, not
|
|
230
|
+
proof of server acceptance or a complete traffic denominator.
|
|
231
|
+
|
|
232
|
+
At most once per minute per process, the worker freezes an identified report of
|
|
233
|
+
routine eligible observations; an explicit flush may send it sooner. Reports
|
|
234
|
+
contain controller/action names and counts only: `observed`, `retained` (selected
|
|
235
|
+
for enqueue), `sampled_out`, and `queue_dropped` (a subset of retained). They never
|
|
236
|
+
contain event properties or user/account identifiers. Counts are observed after
|
|
237
|
+
validation, redaction, and `before_send`; hooks that suppress events, crashes,
|
|
238
|
+
protected requests, and unknown endpoint names are outside this denominator.
|
|
239
|
+
Retained counts are not accepted counts. The resulting request percentiles and
|
|
240
|
+
rates cannot be treated as an unbiased whole-traffic distribution.
|
|
241
|
+
|
|
242
|
+
Reports have immutable UUIDs/bodies and separate durable acknowledgments. They
|
|
243
|
+
can travel in `events: []` batches without consuming event quota, and an
|
|
244
|
+
acknowledged report does not establish delivery of its accompanying events.
|
|
245
|
+
Counters cover at most 100 endpoint names per window, reports share the normal
|
|
246
|
+
batch byte limit, and each process retains at most five unacknowledged reports.
|
|
247
|
+
Overflows or invalid clock windows mark coverage `limited`; reports older than
|
|
248
|
+
seven days are discarded. This is bounded in-memory observation, not a durable
|
|
249
|
+
request ledger. Unacknowledged reports after a confirmed handshake can cause
|
|
250
|
+
`RailsMind.flush` to return false at its deadline.
|
|
251
|
+
|
|
252
|
+
## Jobs and mailer workflows
|
|
253
|
+
|
|
254
|
+
With `apm` enabled, the SDK automatically observes installed ActiveJob and Action
|
|
255
|
+
Mailer components. No SMTP-provider integration or OpenTelemetry setup is required.
|
|
256
|
+
It does not change the queue adapter, delivery provider, retry policy, or error
|
|
257
|
+
handling. Both integrations respect `RailsMind.suppress` and the normal collector
|
|
258
|
+
bounds. Request, job, and mailer identity/release context uses the existing core
|
|
259
|
+
fields; job arguments and email contents are never inspected for correlation.
|
|
260
|
+
|
|
261
|
+
The versioned property contract is `schema_version: 1` with `instrumentation`
|
|
262
|
+
equal to `active_job` or `action_mailer`:
|
|
263
|
+
|
|
264
|
+
| Component | Observations | Selected metadata |
|
|
265
|
+
| --- | --- | --- |
|
|
266
|
+
| ActiveJob | `enqueue`, `enqueue_at`, `perform_start`, `perform`, `enqueue_retry`, `retry_stopped`, `discard` | Class, queue, execution count, enqueue/schedule timestamps, queue delays |
|
|
267
|
+
| Action Mailer | `process`, `delivery_attempt_completed`, `delivery_not_observed` | Mailer/action, opaque attempt UUID when available, transport class, ordinary/forced invocation, delivery flags, exposed exception class |
|
|
268
|
+
|
|
269
|
+
New enqueue/start and mailer observations use `span`, so they do not inflate
|
|
270
|
+
business-event counts or the existing `job` execution/retry/discard feed. A
|
|
271
|
+
render-only mailer has a processing observation, not a delivery attempt. The
|
|
272
|
+
attempt UUID groups processing with its delivery invocation; retries create new
|
|
273
|
+
attempt UUIDs while the serialized job retains its correlation identifiers.
|
|
274
|
+
|
|
275
|
+
`queue_delay_ms` measures enqueue to execution start, including intentional
|
|
276
|
+
scheduling. `eligible_queue_delay_ms` subtracts intentional scheduling when the
|
|
277
|
+
required timestamps are available, with a zero floor. Missing timestamps remain
|
|
278
|
+
unknown. Retry handlers keep execution context after normal perform callbacks
|
|
279
|
+
unwind. These notifications are best-effort observations, not a durable queue
|
|
280
|
+
ledger: bulk/direct backend APIs may bypass them, and a missing completion does
|
|
281
|
+
not by itself prove a stuck job.
|
|
282
|
+
|
|
283
|
+
Mailer status describes local evidence. `observed` means the local call or
|
|
284
|
+
notification completed; `disabled` identifies ordinary delivery with
|
|
285
|
+
`perform_deliveries: false`; `error` requires an exposed exception. A callback
|
|
286
|
+
abort or other invocation that never reaches the transport is recorded as
|
|
287
|
+
`delivery_not_observed`, with `aborted`, `error`, or `unknown` as appropriate.
|
|
288
|
+
Forced delivery bypasses normal delivery flags and is observed separately.
|
|
289
|
+
Hidden transport failures (`raise_delivery_errors: false`) can still produce an
|
|
290
|
+
`observed` result. None of these establishes provider acceptance or inbox
|
|
291
|
+
arrival; recipient delivery remains unknown.
|
|
292
|
+
|
|
293
|
+
The SDK excludes recipients, sender addresses, subjects, bodies, attachments,
|
|
294
|
+
message IDs/headers, mailer/job arguments, credentials, and provider responses.
|
|
295
|
+
Only transport class names are selected, never transport settings. Rendering a
|
|
296
|
+
mailer and sending its content through a separate HTTP provider client produces
|
|
297
|
+
only the rendering evidence; add explicit reviewed app events or provider
|
|
298
|
+
callbacks if later delivery facts are needed. Keep real product outcomes such
|
|
299
|
+
as invitation acceptance separate, using explicit events after persistence.
|
|
184
300
|
|
|
185
|
-
Jobs record duration, failure/retry/discard lifecycle, execution count, queue name, and enqueue-to-start delay where ActiveJob exposes it. Scheduled delay is included in the enqueue-to-start number. Signals do not include arguments. Full metrics/logs SDK integration is deferred; v0.1 computes hosted aggregates from unsampled request events and does not capture application logs.
|
|
186
301
|
|
|
187
302
|
## Flipper and browser behavior
|
|
188
303
|
|
|
@@ -200,16 +315,18 @@ Add `<meta name="rails-mind-page" content="Invoices#index">` to supply a stable
|
|
|
200
315
|
|
|
201
316
|
## Bounds, privacy, and outages
|
|
202
317
|
|
|
203
|
-
Defaults are one lazy worker per process, 1,000 queued/in-flight events, 16 KiB per event, at most 100 events and 256 KiB per batch, and a two-second flush interval. Overflow drops the newest event. Retries retain the same encoded bytes/UUIDs; only HTTP 429, 5xx, and transient transport failures retry, at most three retries with bounded backoff. Other 4xx responses
|
|
318
|
+
Defaults are one lazy worker per process, 1,000 queued/in-flight events, 16 KiB per event, at most 100 events and 256 KiB per batch, and a two-second flush interval. Overflow drops the newest event. Retries retain the same encoded bytes/UUIDs; only HTTP 429, 5xx, and transient transport failures retry, at most three retries with bounded backoff. Other 4xx responses end delivery attempts. A failed response can follow partial server acceptance, so such events are classified as delivery unconfirmed. Redirects are not followed. Shutdown gets two seconds by default, then discards outstanding telemetry; forks start a fresh child queue rather than resending the parent's buffer.
|
|
204
319
|
|
|
205
320
|
```ruby
|
|
206
321
|
RailsMind.stats
|
|
207
|
-
# => { enqueued:, delivered:, dropped:, retried:, queued:, in_flight:,
|
|
208
|
-
# losses: { "event.overflow" => 3, "error.
|
|
322
|
+
# => { enqueued:, delivered:, dropped:, delivery_unconfirmed:, retried:, queued:, in_flight:,
|
|
323
|
+
# losses: { "event.overflow" => 3, "error.delivery_unconfirmed" => 1 },
|
|
324
|
+
# sampling: { observed:, retained:, sampled_out:, queue_dropped:,
|
|
325
|
+
# unreported:, reports_lost:, pending_reports:, limited:, policy_state:, policy_id: } }
|
|
209
326
|
RailsMind.flush(timeout: 2)
|
|
210
327
|
```
|
|
211
328
|
|
|
212
|
-
These are per-process counters. The doctor prints
|
|
329
|
+
These are per-process counters. `dropped` counts known local discards, such as queue overflow or oversize payloads. `delivery_unconfirmed` counts events whose delivery attempts ended without a success response, including interrupted in-flight batches; some may have been accepted by the server. `delivered` counts submitted events in batches with a successful HTTP response; it does not prove server retention or background processing. The doctor prints stats for its process; inspect running app stats through your existing operational tooling. Only the routine-request report above sends queue-loss observations to the hosted app. All signal kinds can still undercount after crashes, rejected payloads, hooks, or outages. This is best-effort monitoring, not an accounting ledger; use a transactional outbox when durable business-event delivery is required.
|
|
213
330
|
|
|
214
331
|
Redaction occurs before buffering and again after custom `before_send`. Sensitive property names are filtered, nesting/string/collection sizes are capped, emails and common credential forms are scrubbed, exception messages are omitted by default, and backtraces drop machine-home prefixes. Bodies, cookies, credentials, SQL binds, and job arguments are never selected by integrations. Arbitrary user-provided text may contain sensitive content that generic redaction cannot recognize: use small, explicitly reviewed business properties. Opting into exception messages requires reviewing `capture_exception_message` and your custom scrubbing policy.
|
|
215
332
|
|
|
@@ -223,3 +340,10 @@ This historical check used an internal sample application that is not included
|
|
|
223
340
|
in the public client repository. To verify your own installation, follow
|
|
224
341
|
[Verify the connection](#verify-the-connection). External hosted deployment and
|
|
225
342
|
published-gem installation remain unverified by that historical check.
|
|
343
|
+
|
|
344
|
+
## Connect your coding agent
|
|
345
|
+
|
|
346
|
+
Run `bin/rails generate rails_mind:agent --plan` to preview the connection setup.
|
|
347
|
+
The [agent guide](agents.md) covers Claude Code and Codex, environment-variable and
|
|
348
|
+
Rails credentials authentication, safe verification, and the complete fix journey.
|
|
349
|
+
The agent API token is separate from `RAILS_MIND_KEY`, the ingestion key above.
|