Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,20 +167,11 @@ bin/workflow [options] [command] [arguments]

This repo uses `.githooks/` directory for git hooks. The pre-commit hook runs `bin/ci` which includes `bin/lint-r3x` to verify AGENTS.md references.

## Static Typing

- This repo uses RBS + Steep for static type checks. The current Steep scope is intentionally narrow and starts with the workflow-facing API contract.
- Run `bin/typecheck` after changing files covered by `Steepfile`.
- When changing `R3x::Workflow::Context`, `R3x::Workflow::Context::Client`, or `R3x::Client::Http`, update the matching files under `sig/`.
- When adding a new workflow client method to `R3x::Workflow::Context::Client`, add its RBS signature and any minimal dependency stub needed for `bin/typecheck`.
- Keep the Steep scope narrow. Do not expand it to the whole Rails app unless explicitly planned.
- Treat `sig/r3x/client/_stubs.rbs` and `sig/r3x/external_stubs.rbs` as dependency stubs, not source of truth for unchecked implementation details.

## Iterative Design Reviews

- When the user is still reviewing the shape of a refactor or API design, keep the first pass focused on production code only unless they explicitly ask for full follow-through.
- Do not update tests, fixtures, or RBS signatures for an unaccepted design sketch. Wait until the user accepts the code shape, then synchronize tests and `sig/` files in the follow-up pass.
- It is still fine to run syntax checks on the touched Ruby files during the sketch phase. Do not treat typecheck failures caused only by intentionally stale RBS as blockers until the user accepts the design.
- Do not update tests or fixtures for an unaccepted design sketch. Wait until the user accepts the code shape, then synchronize tests in the follow-up pass.
- It is still fine to run syntax checks on the touched Ruby files during the sketch phase.

## JSON

Expand Down
4 changes: 0 additions & 4 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,6 @@ group :development, :test do
gem "rubocop-minitest", require: false
gem "rubocop-thread_safety", "~> 0.7.3", require: false

# Narrow static type-checking spike for workflow-facing API contracts.
gem "rbs", require: false
gem "steep", require: false

# Auto-load environment variables from .env file
gem "dotenv-rails", require: false
end
Expand Down
59 changes: 0 additions & 59 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ GEM
bigdecimal
rexml
crass (1.0.6)
csv (3.3.5)
date (3.5.1)
debug (1.11.1)
irb (~> 1.10)
Expand Down Expand Up @@ -123,15 +122,6 @@ GEM
net-http (~> 0.5)
faraday-retry (2.4.0)
faraday (~> 2.0)
ffi (1.17.4-aarch64-linux-gnu)
ffi (1.17.4-aarch64-linux-musl)
ffi (1.17.4-arm-linux-gnu)
ffi (1.17.4-arm-linux-musl)
ffi (1.17.4-arm64-darwin)
ffi (1.17.4-x86_64-darwin)
ffi (1.17.4-x86_64-linux-gnu)
ffi (1.17.4-x86_64-linux-musl)
fileutils (1.8.0)
fugit (1.12.2)
et-orbi (~> 1.4)
raabro (~> 1.4)
Expand Down Expand Up @@ -277,10 +267,6 @@ GEM
base64
language_server-protocol (3.17.0.5)
lint_roller (1.1.0)
listen (3.10.0)
logger
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
logger (1.7.0)
loofah (2.25.1)
crass (~> 1.0.2)
Expand Down Expand Up @@ -408,13 +394,6 @@ GEM
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.4.2)
rb-fsevent (0.11.2)
rb-inotify (0.11.1)
ffi (~> 1.0)
rbs (4.0.2)
logger
prism (>= 1.6.0)
tsort
rdoc (7.2.0)
erb
psych (>= 4.0.0)
Expand Down Expand Up @@ -504,28 +483,9 @@ GEM
sqlite3 (2.9.5-x86_64-darwin)
sqlite3 (2.9.5-x86_64-linux-gnu)
sqlite3 (2.9.5-x86_64-linux-musl)
steep (2.0.0)
concurrent-ruby (>= 1.1.10)
csv (>= 3.0.9)
fileutils (>= 1.1.0)
json (>= 2.1.0)
language_server-protocol (>= 3.17.0.4, < 4.0)
listen (~> 3.0)
logger (>= 1.3.0)
parser (>= 3.2)
prism (>= 0.25.0)
rainbow (>= 2.2.2, < 4.0)
rbs (~> 4.0)
securerandom (>= 0.1)
strscan (>= 1.0.0)
terminal-table (>= 2, < 5)
uri (>= 0.12.0)
stimulus-rails (1.3.4)
railties (>= 6.0.0)
stringio (3.2.0)
strscan (3.1.8)
terminal-table (4.0.0)
unicode-display_width (>= 1.1.1, < 4)
thor (1.5.0)
timeout (0.6.1)
trailblazer-option (0.1.2)
Expand Down Expand Up @@ -585,7 +545,6 @@ DEPENDENCIES
propshaft
puma (>= 5.0)
rails (~> 8.1.2)
rbs
retryable (~> 3.0)
rss
rubocop-minitest
Expand All @@ -596,7 +555,6 @@ DEPENDENCIES
solid_cache
solid_queue
sqlite3 (>= 2.1)
steep
webmock

CHECKSUMS
Expand Down Expand Up @@ -625,7 +583,6 @@ CHECKSUMS
connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a
crack (1.0.1) sha256=ff4a10390cd31d66440b7524eb1841874db86201d5b70032028553130b6d4c7e
crass (1.0.6) sha256=dc516022a56e7b3b156099abc81b6d2b08ea1ed12676ac7a5657617f012bd45d
csv (3.3.5) sha256=6e5134ac3383ef728b7f02725d9872934f523cb40b961479f69cf3afa6c8e73f
date (3.5.1) sha256=750d06384d7b9c15d562c76291407d89e368dda4d4fff957eb94962d325a0dc0
debug (1.11.1) sha256=2e0b0ac6119f2207a6f8ac7d4a73ca8eb4e440f64da0a3136c30343146e952b6
declarative (0.0.20) sha256=8021dd6cb17ab2b61233c56903d3f5a259c5cf43c80ff332d447d395b17d9ff9
Expand All @@ -641,15 +598,6 @@ CHECKSUMS
faraday-multipart (1.2.0) sha256=7d89a949693714176f612323ca13746a2ded204031a6ba528adee788694ef757
faraday-net_http (3.4.4) sha256=0e78af151747ed1b00f33e25973b4bc220d7f16c00c39676817c8b12331eb588
faraday-retry (2.4.0) sha256=7b79c48fb7e56526faf247b12d94a680071ff40c9fda7cf1ec1549439ad11ebe
ffi (1.17.4-aarch64-linux-gnu) sha256=b208f06f91ffd8f5e1193da3cae3d2ccfc27fc36fba577baf698d26d91c080df
ffi (1.17.4-aarch64-linux-musl) sha256=9286b7a615f2676245283aef0a0a3b475ae3aae2bb5448baace630bb77b91f39
ffi (1.17.4-arm-linux-gnu) sha256=d6dbddf7cb77bf955411af5f187a65b8cd378cb003c15c05697f5feee1cb1564
ffi (1.17.4-arm-linux-musl) sha256=9d4838ded0465bef6e2426935f6bcc93134b6616785a84ffd2a3d82bc3cf6f95
ffi (1.17.4-arm64-darwin) sha256=19071aaf1419251b0a46852abf960e77330a3b334d13a4ab51d58b31a937001b
ffi (1.17.4-x86_64-darwin) sha256=aa70390523cf3235096cf64962b709b4cfbd5c082a2cb2ae714eb0fe2ccda496
ffi (1.17.4-x86_64-linux-gnu) sha256=9d3db14c2eae074b382fa9c083fe95aec6e0a1451da249eab096c34002bc752d
ffi (1.17.4-x86_64-linux-musl) sha256=3fdf9888483de005f8ef8d1cf2d3b20d86626af206cbf780f6a6a12439a9c49e
fileutils (1.8.0) sha256=8c6b1df54e2540bdb2f39258f08af78853aa70bad52b4d394bbc6424593c6e02
fugit (1.12.2) sha256=643f2bf28db263bd400cbf8e0dd8b76b2c9b94bdb130e12d2394de04d9c20e5e
gapic-common (1.3.0) sha256=4e5d9be1effb7366e2cda13c0f44922285d5613ac8de8b9b18c2c835fe4faa91
globalid (1.3.0) sha256=05c639ad6eb4594522a0b07983022f04aa7254626ab69445a0e493aa3786ff11
Expand Down Expand Up @@ -697,7 +645,6 @@ CHECKSUMS
jwt (3.2.0) sha256=5419b1fe37b1da0982bd07051f573a8b8789ab724c2aa7e785e4784a3ed217d7
language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc
lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
listen (3.10.0) sha256=c6e182db62143aeccc2e1960033bebe7445309c7272061979bb098d03760c9d2
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
loofah (2.25.1) sha256=d436c73dbd0c1147b16c4a41db097942d217303e1f7728704b37e4df9f6d2e04
mail (2.9.0) sha256=6fa6673ecd71c60c2d996260f9ee3dd387d4673b8169b502134659ece6d34941
Expand Down Expand Up @@ -753,9 +700,6 @@ CHECKSUMS
railties (8.1.3) sha256=913eb0e0cb520aac687ffd74916bd726d48fa21f47833c6292576ef6a286de22
rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
rb-fsevent (0.11.2) sha256=43900b972e7301d6570f64b850a5aa67833ee7d87b458ee92805d56b7318aefe
rb-inotify (0.11.1) sha256=a0a700441239b0ff18eb65e3866236cd78613d6b9f78fea1f9ac47a85e47be6e
rbs (4.0.2) sha256=af75671e66cd03434cc546622741ebf83f6197ec4328375805306330bf78ef25
rdoc (7.2.0) sha256=8650f76cd4009c3b54955eb5d7e3a075c60a57276766ebf36f9085e8c9f23192
regexp_parser (2.12.0) sha256=35a916a1d63190ab5c9009457136ae5f3c0c7512d60291d0d1378ba18ce08ebb
reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835
Expand Down Expand Up @@ -787,11 +731,8 @@ CHECKSUMS
sqlite3 (2.9.5-x86_64-darwin) sha256=8e9caae38bd7ebb29cbeee3e7ab1d12dc2327d9a1b92c7fcf0dda05589627a81
sqlite3 (2.9.5-x86_64-linux-gnu) sha256=233dbcb6714148dd23bc5aeb33e8efd6eac974969564ddd5794c23d5f52b231e
sqlite3 (2.9.5-x86_64-linux-musl) sha256=e7d3a7474e8af0f96150c21abc203fbab5437206bfcdf11deab7741c0ca516f2
steep (2.0.0) sha256=6eb0ecc09637bbb54f0a5f2cf63daea6d3208ccace64b4f1107d976333605c30
stimulus-rails (1.3.4) sha256=765676ffa1f33af64ce026d26b48e8ffb2e0b94e0f50e9119e11d6107d67cb06
stringio (3.2.0) sha256=c37cb2e58b4ffbd33fe5cd948c05934af997b36e0b6ca6fdf43afa234cf222e1
strscan (3.1.8) sha256=aae2db611a225559f21ffbb71765c9a4e60fd262534a9ea84f4f11c7f32f679e
terminal-table (4.0.0) sha256=f504793203f8251b2ea7c7068333053f0beeea26093ec9962e62ea79f94301d2
thor (1.5.0) sha256=e3a9e55fe857e44859ce104a84675ab6e8cd59c650a49106a05f55f136425e73
timeout (0.6.1) sha256=78f57368a7e7bbadec56971f78a3f5ecbcfb59b7fcbb0a3ed6ddc08a5094accb
trailblazer-option (0.1.2) sha256=20e4f12ea4e1f718c8007e7944ca21a329eee4eed9e0fa5dde6e8ad8ac4344a3
Expand Down
24 changes: 0 additions & 24 deletions Steepfile

This file was deleted.

6 changes: 0 additions & 6 deletions bin/typecheck

This file was deleted.

1 change: 0 additions & 1 deletion config/ci.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
step "Style: Ruby", "bin/rubocop"
step "Style: YAML", "bin/dprint check"
step "Lint: AGENTS.md references", "bin/lint-r3x"
step "Types: Static Types", "bin/typecheck"

step "Security: Gem audit", "bin/bundler-audit"
step "Security: Brakeman code analysis", "bin/brakeman --quiet --no-pager --exit-on-warn --exit-on-error"
Expand Down
29 changes: 10 additions & 19 deletions docs/todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,34 +163,26 @@ This is brittle against interpreter changes and hard to understand.

## Phase 4 — long-term / optional

### [x] K. RBS signatures are stale for new clients
### [x] K. Remove RBS + Steep static type checks

**Files:** `sig/r3x/client/*.rbs`, `Steepfile`
**Files:** `sig/`, `Steepfile`, `bin/typecheck`, `Gemfile`, `config/ci.rb`

**Done:**

- Added per-client RBS signatures under `sig/r3x/client/` for:
- `apify`, `discord`, `google/gmail`, `google/translate`, `google_sheets`, `healthchecks_io`, `markdownify`, `ocr`, `prometheus`, `llm` (and nested `Classifier`, `ProviderConfiguration`, `ProviderRegistry`).
- Added signatures for client result/response objects: `Ocr::Result`, `HealthchecksIO::Response`, `Prometheus::Result`.
- Removed the stale `sig/r3x/workflow/base.rbs` (the class was not in `Steepfile` and the signature was incomplete).
- Removed the consolidated `sig/r3x/client/_stubs.rbs` in favor of explicit per-client signature files.
- Added the new clients to `Steepfile` so `bin/typecheck` covers them.
- Added missing dependency stubs to `sig/r3x/external_stubs.rbs` (`HTTPX.get/post/head`, `R3x::Env.fetch!`, `R3x::Client::GoogleAuth`, `Google::Apis::*`, `Mail::Part`, `RubyLLM`, `SecureRandom`, `Base64`, `String#blank?`).
- Made small code tweaks to keep type-checking clean:
- `Ocr#build_params` now starts with an empty `Hash.new`.
- `Llm` uses `Hash.new` for class-level caches and an explicit block param instead of `it`.
- `Google::Translate#translate` validates the translations array explicitly.
- `Google::Gmail#raw_message` uses an explicit `Mail::Part` block param.

**Verification:** `bin/typecheck` passes; `bin/rails test` passes; `bin/lint-r3x` passes.
- Removed the `sig/` directory, `Steepfile`, and `bin/typecheck` script.
- Removed `rbs` and `steep` gems from `Gemfile` and regenerated `Gemfile.lock`.
- Removed the "Types: Static Types" step from `config/ci.rb`.
- Removed the Static Typing section from `AGENTS.md` and updated references in `docs/todo.md`.

**Reason:** Steep does not yet support Ruby 3.4's `it` block parameter (see https://github.com/soutaro/steep/pull/2238). Keeping RBS signatures in sync was also adding friction without enough payoff at the current project size. Static typing can be reintroduced once the upstream blocker is resolved.

---

### [ ] L. Pre-commit hook runs the full CI suite

**File:** `.githooks/pre-commit`

The hook runs `bin/ci`, which includes `bin/lint-r3x`, RuboCop, dprint, typecheck, bundler-audit, brakeman, and the full test suite. This can be slow for every commit.
The hook runs `bin/ci`, which includes `bin/lint-r3x`, RuboCop, dprint, bundler-audit, brakeman, and the full test suite. This can be slow for every commit.

**Suggested fix:** consider a lighter pre-commit (format + lint references) and run the full suite on push / in CI.

Expand All @@ -203,8 +195,7 @@ These are not actionable todos yet; they are framing notes for larger refactor d
### DHH / 37signals perspective

- **Less layering, more Rails.** Much of `app/lib/r3x/dashboard/workflow/` (`Catalog`, `Summaries`, `Runs`) is logic that belongs in models under `app/models/dashboard/`, not in parallel service/query layers. `Dashboard::Run` is the model — let it own its queries and summaries.
- **Pre-commit running full CI is expensive.** Running `bin/ci` (RuboCop, dprint, typecheck, bundler-audit, brakeman, full test suite) on every commit slows the local loop. A lighter pre-commit with full CI on push is more Rails-like.
- **RBS/Steep may be overhead at this size.** Keeping signatures in sync is a tax. If the team is not actively relying on Steep, the narrow scope is good, but widening it would be a mistake.
- **Pre-commit running full CI is expensive.** Running `bin/ci` (RuboCop, dprint, bundler-audit, brakeman, full test suite) on every commit slows the local loop. A lighter pre-commit with full CI on push is more Rails-like.
- **Fail fast, don't swallow errors.** `R3x::Env.load_from_vault` catching `StandardError` violates the 37signals preference for loud failures over silent degradation.
- **Use your own conventions everywhere.** Direct `ENV.fetch` calls in `config/puma.rb` and `production.rb` undermine the `R3x::Env` helper and create inconsistent semantics.

Expand Down
24 changes: 0 additions & 24 deletions sig/r3x/client/apify.rbs

This file was deleted.

17 changes: 0 additions & 17 deletions sig/r3x/client/discord.rbs

This file was deleted.

21 changes: 0 additions & 21 deletions sig/r3x/client/google/gmail.rbs

This file was deleted.

25 changes: 0 additions & 25 deletions sig/r3x/client/google/translate.rbs

This file was deleted.

21 changes: 0 additions & 21 deletions sig/r3x/client/google_sheets.rbs

This file was deleted.

Loading
Loading