Ethotrace

Ethotrace は Ruby 向けの動的型検査・シグネチャ解析システム。公称型(型名)ではなく、 テスト実行中のメソッド呼び出しを観測して「振る舞い(プロトコル)」「伝播例外」 「実行環境要件(Requirements)」を三チャネルで記録する。

設計思想は Effect-TS の Effect<Success, Error, Requirements> モデルに着想を得ている。 詳細な設計は docs/ethotrace-design-handoff-v2.md、 gem 間の安定契約である JSONL スキーマは docs/schema.md を参照。

観測結果は observed contract(観測された下限) であり、テストカバレッジに依存する。 未実行パスの規約は含まれない。これは欠陥ではなく仕様である。

モノレポ構成

単一リポジトリに複数 gem を置くモノレポ構成(段階的に追加予定):

gem 役割
gems/ethotrace core: 観測エンジン + stdlib アダプタ + JSONL ライター + マージ CLI
gems/ethotrace-rspec RSpec ライフサイクル接続
gems/ethotrace-minitest Minitest 版(予定)
gems/ethotrace-rails Railtie / ActiveSupport::Notifications / Zeitwerk 連携(予定)
gems/ethotrace-mcp 観測結果を提供する MCP サーバ(観測プロセスと完全分離)
gems/ethotrace-rbs RBS interface への投影(予定)

実装状況

マイルストーン 内容 状態
M0 スキャフォールド + スキーマ v1 確定
M1 prepend ラッパー + Tracker + CallContext + 再入ガード + JSONL ライター(Success / Error チャネル)
M2 アダプタ API + stdlib アダプタ(ENV/Time/Random/IO/Process)+ Requirements 帰属 + エフェクトスパン
M3 TracePoint エンジン + 引数プロトコル観測
M4 ethotrace-rspec(スイートライフサイクル接続)+ マージ CLI(ethotrace merge)
M5 自己適用(self-hosting)+ 隔離戦略(NullIsolation / BoxIsolation)+ collector/probe 分離
M6 ethotrace-mcp(自己観測データを参照する MCP サーバ)
M7 ethotrace-rails(Railtie / Notifications / Zeitwerk) 予定
M8 ethotrace-rbs(protocol → RBS interface 投影) 予定

ロードマップは設計資料 v2 で改定済み: MCP を Rails より先に作る。M5 で自己適用を達成し、 M6 の MCP 経由で以降の開発を自己観測データで支援するブートストラップループに入る(§9)。

core の使い方は gems/ethotrace/README.md を参照。

使い方(RSpec)

ethotrace-rspec をテストに組み込むと、スイート開始/終了に観測セッションが接続され、 テストワーカーごとに tmp/ethotrace/<session>.jsonl が書き出される。spec_helper.rb で:

require "ethotrace/rspec"

Ethotrace::RSpec.setup do |config|
  config.observe Order                  # Order 自身のインスタンスメソッド全部
  config.observe Tax, methods: %i[rate] # 一部メソッドだけを指定
  # config.options[:trace_c_call] = true  # C メソッドもプロトコルに含める(高コスト)
end

並列テスト(parallel_tests)ではワーカーごとに TEST_ENV_NUMBER と PID から セッション ID を導出し(例: rspec-w2-pid4242)、別ファイルへ書き分ける。

マージ(ethotrace merge)

並列ワーカーが吐いた複数の JSONL を 1 つへ統合する。(owner, name, kind) をキーに、 プロトコル・例外・Requirements を和集合、samples を加算する(→ docs/schema.md §7)。

bundle exec ethotrace merge tmp/ethotrace/*.jsonl -o ethotrace/observations.jsonl

出力は method_observation 形を 1 行 1 レコードで保つため再マージ可能-o を省略すると標準出力へ純粋な JSONL を流す(進捗・サマリは標準エラーへ)。 マージ結果は ethotrace view でそのまま閲覧できる。

MCP サーバ(ethotrace-mcp)

マージ済みの観測結果を MCP サーバ(stdio / JSON-RPC) として公開し、AI エージェント (第一のユーザーは Ethotrace を開発する Claude Code 自身)が各メソッドの規約を参照しながら 開発を進められるようにする。観測プロセスとは完全分離したデータ消費者で、計装は一切起動 しない(設計資料 §9 / M6)。

# 既定で ethotrace/observations.jsonl を読み、stdio で待ち受ける
bundle exec ethotrace-mcp
bundle exec ethotrace-mcp path/to/observations.jsonl   # 読むストアを明示

Claude Code へは .mcp.json.example.mcp.json にコピーするとプロジェクトスコープの MCP サーバとして登録される。公開ツール:

ツール 返すもの
lookup_method 1 メソッドの全規約(プロトコル・戻り値・例外・Requirements)
list_methods 観測された全メソッド
pure_methods Requirements が空(R=∅ = 純粋の容疑)
flaky_suspects 非決定性 Requirements(time.read / random.read 等)に接触
requiring 特定エフェクト語彙(db.query / env.read 等)に接触
methods_raising / exceptions_of 例外をエスケープさせうるメソッド / その例外クラス
param_protocol 指定引数に観測されたプロトコル

返る規約は observed contract(テストで実行されたパスの下限)。詳しい自己観測ループの手順は CLAUDE.md を参照。

自己適用(self-hosting)と隔離戦略

Ethotrace は 観測の設置先を差し替え可能な隔離戦略(Ethotrace::Isolation)として持つ。 probe(prepend フック)を「どの空間で」走らせるかだけを戦略が決め、collector(記録・帰属・ JSONL)と TracePoint は常に root 側に置く。

戦略 条件 用途
Isolation::Null 既定 通常の解析(probe = collector 同一空間)
Isolation::Box Ruby >= 4.0 + RUBY_BOX=1 自己適用・モンキーパッチの激しい対象

Isolation::Box は子 Ruby::Box(Ruby 4.0 experimental)に Ethotrace を新規ロードし、観測対象を root と別実体に隔離する。これにより 「計装機構そのものが計装対象になる」自己言及汚染が構造的に解ける。観測イベントは box 内 probe から root の Collector へ橋渡しされる。加えて記録の活性パスは名前ベースの deny-list (Wrapper::SELF_DENY_LIST)で二重に保護する。

# 自己適用デモ: Ethotrace で Ethotrace 自身のメソッドを観測する(main box から起動)
RUBY_BOX=1 ruby gems/ethotrace/script/self_hosting.rb

Ruby::Box の検証結果(実体分離・越境観測・系譜依存など E1〜E6)は docs/box-semantics.md に、設計の詳細は設計資料 §4.8 に記す。 Ruby::Box は experimental かつ main box からの起動を要するため、自己適用の検証は上記の スタンドアロンハーネス(素の RUBY_BOX=1 ruby)で行う(RUBY_BOX=1 下では bundler/rspec が stdlib autoload の問題で動かない)。Rails アダプタ + BoxIsolation の併用は当面サポート外

開発

Ruby >= 3.2 が必要。

bundle install          # 依存解決(ルートの Gemfile が全 gem を束ねる)
bundle exec rake        # 全 gem の spec + RuboCop
bundle exec rake spec   # テストのみ
bundle exec rake rubocop

ライセンス

MIT