uproad/ethotrace

GitHub: uproad/ethotrace

一个通过观测 Ruby 测试运行时行为来动态推导方法签名与类型契约的分析工具。

Stars: 0 | Forks: 0

# Ethotrace **Ethotrace** 是一个面向 Ruby 的动态类型检查与 signature 解析系统。它不依赖于 nominal type (类型名), 而是通过观察测试执行期间的 method 调用,在三个 channel 中记录“行为”、“传播的 exception” 以及“执行环境要求”。其设计思想受到了 Effect-TS 的 `Effect` 模型的启发。 详细设计请参阅 [`docs/ethotrace-design-handoff-v2.md`](docs/ethotrace-design-handoff-v2.md), 作为 gem 之间稳定契约的 JSONL schema 请参阅 [`docs/schema.md`](docs/schema.md)。 ## Monorepo 结构 采用在单一 repository 中放置多个 gem 的 monorepo 结构(计划逐步添加): | gem | 作用 | |---|---| | `gems/ethotrace` | core: 观测引擎 + stdlib adapter + JSONL writer + 合并 CLI | | `gems/ethotrace-rspec` | RSpec 生命周期接入 | | `gems/ethotrace-minitest` | Minitest 版(计划中) | | `gems/ethotrace-rails` | Railtie / ActiveSupport::Notifications / Zeitwerk 集成(计划中) | | `gems/ethotrace-mcp` | 提供观测结果的 MCP server(与观测进程完全隔离) | | `gems/ethotrace-rbs` | 向 RBS interface 映射(计划中) | ## 实现状态 | 里程碑 | 内容 | 状态 | |---|---|---| | M0 | scaffold + schema v1 确定 | ✅ | | M1 | prepend wrapper + Tracker + CallContext + 可重入 guard + JSONL writer (Success / Error channel) | ✅ | | M2 | adapter API + stdlib adapter (ENV/Time/Random/IO/Process) + Requirements 归因 + effect span | ✅ | | M3 | TracePoint 引擎 + 参数 protocol 观测 | ✅ | | M4 | `ethotrace-rspec`(suite 生命周期接入)+ 合并 CLI (`ethotrace merge`) | ✅ | | M5 | 自我应用 + 隔离策略 (`NullIsolation` / `BoxIsolation`) + collector/probe 分离 | ✅ | | M6 | `ethotrace-mcp`(参考自身观测数据的 MCP server) | ✅ | | M7 | `ethotrace-rails`(Railtie / Notifications / Zeitwerk) | 计划中 | | M8 | `ethotrace-rbs`(protocol → RBS `interface` 映射) | 计划中 | core 的使用方法请参阅 [`gems/ethotrace/README.md`](gems/ethotrace/README.md)。 ## 使用方法 如果将 `ethotrace-rspec` 集成到测试中,将在 suite 开始/结束时接入观测 session, 并为每个测试 worker 生成 `tmp/ethotrace/.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 ``` 在并行测试 中,每个 worker 会根据 `TEST_ENV_NUMBER` 和 PID 推导出 session ID(例如:`rspec-w2-pid4242`),并分别写入不同的文件中。 ## 合并 (`ethotrace merge`) 将多个并行 worker 输出的 JSONL 合并为一个。以 `(owner, name, kind)` 为 key, 对 protocol、exception 和 Requirements 取并集,并将 `samples` 累加(→ [`docs/schema.md`](docs/schema.md) §7)。 ``` bundle exec ethotrace merge tmp/ethotrace/*.jsonl -o ethotrace/observations.jsonl ``` 由于输出保持每行一条记录的 `method_observation` 格式,因此**支持再次合并**。 如果省略 `-o`,则会将纯 JSONL 输出到标准输出(进度和摘要输出到标准错误)。 合并后的结果可以直接使用 `ethotrace view` 查看。 ## MCP server (`ethotrace-mcp`) 将合并后的观测结果作为 **MCP server (stdio / JSON-RPC)** 公开,以便 AI agent (首要用户是开发 Ethotrace 的 Claude Code 自身)在开发时能够参考每个 method 的规约。 它是与观测进程**完全隔离**的数据消费者,不会启动任何 instrumentation(设计资料 §9 / M6)。 ``` # 既定で ethotrace/observations.jsonl を読み、stdio で待ち受ける bundle exec ethotrace-mcp bundle exec ethotrace-mcp path/to/observations.jsonl # 読むストアを明示 ``` 如果将 `.mcp.json.example` 复制为 `.mcp.json`,Claude Code 就会将其注册为 project scope 的 MCP server。公开的 tool: | tool | 返回内容 | |---|---| | `lookup_method` | 1 个 method 的所有规约(protocol、返回值、exception、Requirements) | | `list_methods` | 观测到的所有 method | | `pure_methods` | Requirements 为空(R=∅,即有纯粹的嫌疑) | | `flaky_suspects` | 接触了非确定性 Requirements(`time.read` / `random.read` 等) | | `requiring` | 接触了特定 effect 词汇(`db.query` / `env.read` 等) | | `methods_raising` / `exceptions_of` | 可能导致 exception 逃逸的 method / 该 exception 类 | | `param_protocol` | 观测到的指定参数的 protocol | 返回的规约是 **observed contract(在测试执行路径下的下限)**。关于详细的自观测循环步骤, 请参阅 `CLAUDE.md`。 ## 自我应用 和隔离策略 Ethotrace 将 **观测的安装目标** 作为可替换的隔离策略 (`Ethotrace::Isolation`) 提供。 策略仅决定在“哪个空间”运行 probe (prepend hook),而 collector(记录、归因、 JSONL)和 TracePoint 始终放置在 root 侧。 | 策略 | 条件 | 用途 | |---|---|---| | `Isolation::Null` | 默认 | 常规分析(probe = collector 同一空间)| | `Isolation::Box` | Ruby >= 4.0 + `RUBY_BOX=1` | 自我应用及存在大量 monkey patch 的对象 | `Isolation::Box` 会将 Ethotrace 新加载到子 [`Ruby::Box`](https://docs.ruby-lang.org/en/4.0/Ruby/Box.html)(Ruby 4.0 experimental) 中,将观测对象隔离到与 root 不同的实体中。这就在结构上解决了 “instrumentation 机制本身成为被观测对象”的自指污染问题。观测事件会从 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`](docs/box-semantics.md) 中,设计详情见设计资料 §4.8。 由于 Ruby::Box 是 experimental 且需要从 main box 启动,因此自我应用的验证需使用上述的 独立测试工具(纯 `RUBY_BOX=1 ruby`)进行(在 `RUBY_BOX=1` 下,由于 stdlib autoload 的问题, bundler/rspec 无法运行)。**目前不提供对 Rails adapter + BoxIsolation 组合使用的支持**。 ## 开发 需要 Ruby >= 3.2。 ``` bundle install # 依存解決(ルートの Gemfile が全 gem を束ねる) bundle exec rake # 全 gem の spec + RuboCop bundle exec rake spec # テストのみ bundle exec rake rubocop ``` ## 许可证 MIT
标签:Ruby, SOC Prime, 代码观测, 动态类型检查, 开发工具, 批量扫描, 时序数据库, 测试工具, 知识库, 签名分析