Mastodonリグレッションスイープ — Rigor v0.1.9での再実行
日時: 2026-05-23。Rigor: v0.1.9(master、[Unreleased])。
対象: mastodon/mastodon。
2つのスイープ:
- パッチライン — 16タグ
v4.5.0-beta.1→v4.5.10、2026-05-21 v0.1.8スイープを現在のエンジンで再実行。 - クロスバージョン — 5つのマイナー/メジャーリリースラインにまたがる9タグ
v3.5.19→v4.5.10(2026-05-23追加)。
以下の§1〜6はスイープ1を、「クロスバージョンスイープ」セクションはスイープ2を扱います。
2026-05-21 Mastodon v4.5.xスイープを再実行します — 同じ対象、同じ16タグ、同じ固定設定で、現在のエンジンに対して。元の実行はRigor v0.1.8上でしたが、エンジンはその後v0.1.9に進んでいます。この再チェックが答える問いは、最初の実行では答えられなかったものです: v0.1.8 → v0.1.9のエンジン変更自体が、実プロジェクトの診断ストリームに影響を与えるか?
手法は変わらず: rigor-regression-sweep手順 — 最初のタグでベースラインを取り、それ以降の各タグに対して固定ベースライン+固定設定でrigor checkを実行。
セットアップ
Section titled “セットアップ”mastodon/mastodonの同じbloblessクローン、同じ16タグをリリース順(v4.5.0-beta.1 … v4.5.10)で — すべての存在を確認済み。- v0.1.8実行と同じ固定設定(全タグで同一を保持):
paths: [app, lib]、exclude: [vendor, tmp]、severity_profile: lenient、signature_paths:→rigor-activesupport-core-extのsig/バンドル(絶対パス)。rigor-*プラグインgemは省略したまま(v0.1.xではRubyGems未公開)。 - 実行前にキャッシュをワイプ。v0.1.8スイープの共有コンテンツハッシュキャッシュを削除し、v0.1.9がすべてのファイルをコールドから再計算するようにしました — エンジンバージョン間のキャッシュエントリーが変化した結果を隠すことがないように。
- v0.1.9で
v4.5.0-beta.1のベースラインを再生成: 30診断 / 25バケット(ルールIDモード)— v0.1.8実行が生成したカウントとバイト単位で同一。 app + libスコープ: beta.1時点で1,218個の.rbファイル、v4.5.10時点で1,219個(v0.1.8実行から変化なし)。
結果 — v0.1.8と同一の、引き続きゼロフラット
Section titled “結果 — v0.1.8と同一の、引き続きゼロフラット”| タグ | raw | サイレンス済み | 浮上 |
|---|---|---|---|
| v4.5.0-beta.1 | 30 | 30 | 0 |
| v4.5.0-beta.2 | 30 | 30 | 0 |
| v4.5.0-rc.1 … -rc.3 | 30 | 30 | 0 |
| v4.5.0 | 30 | 30 | 0 |
| v4.5.1 … v4.5.10 | 30 | 30 | 0 |
全タグ: 浮上 = 0、raw = 30、サイレンス済み = 30。v0.1.9エンジンはv0.1.8スイープをそのまま再現します — 同じベースラインのゼロ起点、16タグ全体にわたって同じゼロフラットの曲線。
チャーンクロスチェック(再測定、v0.1.8実行と同一):
- 119個の
.rbファイルが変更(app + lib内、git diff v4.5.0-beta.1 v4.5.10: 603挿入 / 265削除;リポジトリ全体で762ファイル / 17.3k挿入)。ウィンドウ全体で実際の開発が進行しており、フラットな曲線はno-opのアーティファクトではありません。
v4.5.10のraw構成(コールドキャッシュスポットチェック)
Section titled “v4.5.10のraw構成(コールドキャッシュスポットチェック)”v4.5.10でのv0.1.9による--no-cache --no-baselineコールド実行がraw = 30を独立して確認し、構成はv0.1.8のノートと同一:
| 重要度 | ルール |
|---|---|
| error ×9 | call.undefined-method ×9 |
| warning ×12 | call.possible-nil-receiver ×9、call.argument-type-mismatch ×3 |
| info ×9 | flow.always-truthy-condition ×8、rbs.coverage.missing-gem ×1 |
8件のflow.always-truthy-conditionは、20260521-mastodon-cluster4-flow-folding-triage.mdでトリアージされたクラスタ4のG1/G2フローフォールディング偽陽性 — v0.1.9エンジンでも変化なし。
- v0.1.8 → v0.1.9のエンジン変更はこのコーパスで診断上中立。ベータ1のベースライン、タグごとの浮上曲線、v4.5.10のコールドrawの構成は、2つのエンジンバージョン間でまったく同一です。v0.1.8とv0.1.9の間に出荷されたものは、固定設定下のMastodonの
app + libスコープで診断を1件も追加・削除・変更しませんでした — リリースラインにとって有用なno-regressionシグナル。 - ADR-22のacknowledgeモードは経験的に検証済みのまま。
v4.5.0-beta.1でRigorを採用したプロジェクトは、v4.5.x全ラインを通してベースラインメンテナンスなし・CI偽陽性なしで乗り越えられます — そしてこの結論は1つではなく2つのエンジンバージョンにわたって成立します。 (file, rule, count)ベースラインはエンジンバージョン間でロバスト。v0.1.8で生成されたベースラインとv0.1.9で生成されたベースラインは同じ25バケットをカバーし、パッチバンプ間でルールIDモードのキーイングに何もドリフトしませんでした。
注意点 / この実行の制限
Section titled “注意点 / この実行の制限”- この再実行は元の実行のすべての制限を引き継ぎます。リリースタグはスペックゲート後の母集団であるため、ライン全体での
浮上 = 0はベースラインの安定性を測定するものであり、Rigorのバグ検出能力ではありません。検出のテストにはリリースタグより細かいサンプリングが必要です(コミット単位 / PRhead / バグ導入コミット)— v0.1.8のノート§ CaveatsとSKILL § “Phase 1”を参照。 - 設定は引き続き
rigor-*プラグインを省略(v0.1.xでは未公開);severity_profile: lenientは引き続きpossible-nil-receiver/argument-type-mismatch/flow.*を格下げ。 - 単一プロジェクト、単一リリースライン — コーパスはまだ同じプロジェクト上の2データポイント(この実行とv0.1.8のもの)。
ツーリングノート
Section titled “ツーリングノート”最初の実行が失敗しました: rigorチェックアウトのvendor/bundleが古いRuby ABIに対してコンパイルされたネイティブ拡張(json、prism、rbs)を保持していました — dlopen … Symbol not found: _rb_cObject。Nixデブシェル内でbundle pristineを実行して修正し、すべてのネイティブgemを現在のRuby 4.0.5に対して再コンパイルしました。RubyバンプAfter後にスイープを実行する場合はSKILLに一行追記する価値があります; Rigorのバグではありません。
クロスバージョンスイープ — v3.5.19 → v4.5.10
Section titled “クロスバージョンスイープ — v3.5.19 → v4.5.10”同日に同じv0.1.9エンジンで実行した2番目のスイープは、5つのリリースラインにまたがります: 9タグv3.5.19、v4.0.15、v4.1.15、v4.2.7、v4.3.0-beta.1、v4.3.0、v4.4.0、v4.5.0、v4.5.10。SKILL § “Phase 1”に従い、これはフィーチャースパニングのリリースタグ範囲です — ベースラインがすでにカバーしていない、新しいリリースコードが定常診断を追加するかどうかを測定するもので、パッチラインスイープのベースライン安定性とは別の問いです。
セットアップ
Section titled “セットアップ”- 同じ固定設定形式; v3.5.19で一度ベースラインを取り固定。別のアーティファクトディレクトリ(
_mastodon-major-sweep/)、実行前にキャッシュをワイプ。 app + libスコープは範囲全体で大幅に増加: v3.5.19時点で875個の.rbファイル → v4.5.10時点で1,219個。- データに強制されたパッチスイープからの設定1点の差分 — 以下のパースエラーフロアに関する注記を参照。
パースエラーのフロア — そして設定の修正
Section titled “パースエラーのフロア — そして設定の修正”最初のクロスバージョン実行では、v3.5.19からv4.1.15までの全タグでルールなしのerror診断が常に7件(ベースラインタグ自体を含む)が表示されました。これはSKILL § “Phase 8”が記載する正確なシグネチャです: パースエラーはruleを持たないため、Baselineはそれらをバケットに入れず、永遠に浮上し続けます。原因はlib/templates/rails/post_deployment_migration/migration.rb — .rb拡張子を持つRailsジェネレータERBテンプレート(class <%= … %>はパースに失敗)。これはv4.2.7でアップストリームから削除されており、それがフロアがそこで消える理由です。
SKILLに従い修正は設定側: ジェネレータテンプレートをexclude:します。記録する価値があります — excludeはFile.fnmatch?グロブでFNM_PATHNAMEなし、絶対パスに対してマッチするため、ベアなlib/templatesは何もしません;有効な形式は組み込みexcludesを反映します: "**/lib/templates/**/*.rb"。これを固定exclude:に追加すると、以下の曲線がきれいになります。
結果 — 上昇する浮上曲線
Section titled “結果 — 上昇する浮上曲線”| タグ | ファイル数 | raw | サイレンス済み | 浮上 |
|---|---|---|---|---|
| v3.5.19 | 875 | 22 | 22 | 0 |
| v4.0.15 | 955 | 23 | 22 | 1 |
| v4.1.15 | 961 | 25 | 22 | 3 |
| v4.2.7 | 1022 | 25 | 20 | 5 |
| v4.3.0-beta.1 | 1112 | 28 | 18 | 10 |
| v4.3.0 | 1096 | 31 | 18 | 13 |
| v4.4.0 | 1188 | 29 | 15 | 14 |
| v4.5.0 | 1218 | 30 | 15 | 15 |
| v4.5.10 | 1219 | 30 | 15 | 15 |
ゼロフラットのパッチラインとは異なり、浮上は5つのリリースラインにわたって単調増加で0 → 15まで上昇します。これはフィーチャースパニング範囲の期待される形です: v3.5とv4.5の間に追加されたコードは、v3.5.19のベースラインが知り得なかった診断を持っています。最終的なv4.5.10のセット(15件の浮上)は、パッチスイープがv4.5.0-beta.1でベースラインとした診断クラスタと同じです — call.possible-nil-receiver ×5、call.undefined-method ×4、flow.always-truthy-condition ×3、call.argument-type-mismatch ×3 — つまりv3.5.19のベースラインはv4.5.10の30件の診断のうち15件のみを「新規」として見る;残りの15件はすでにカバー済み。
2つの効果が絡み合っている — 曲線を注意深く読む
Section titled “2つの効果が絡み合っている — 曲線を注意深く読む”クロスメジャースイープは「エラー増加」をきれいに測定するものではありません。2つのことが同時に動きます:
- 真に新しい定常診断 — 新しいファイル / 新しいコードパス(
fasp/ワーカー、interaction_policy_concern、signature_parser)が診断を持っています。上昇の大部分。 - リネームアーティファクト。ベースラインは
(file, rule, count)でキー付けされます。コミットb6b4ea4c(“Move the mastodon/*_cli files to mastodon/cli/*”、#24139)がすべてのCLIファイルをリネームしました —lib/mastodon/statuses_cli.rb→lib/mastodon/cli/statuses.rb。ベースライン化されたcall.undefined-method ×2バケットは:clearedになり、かつ新しいパスが同じ2件の診断を浮上させます:浮上 += 2ですがこれは純粋なチャーン、リグレッションではありません。これはSKILL § “Phase 8”のリネームの注意点が実際に観察されたものです。
サイレンス済み列は反対側から同じ話をしています: コードベースがv3.5.19から離れていくにつれ22 → 15に減衰します — ファイルがリネーム、削除、またはcountを超えて編集されるとベースラインバケットがマッチしなくなります。1,191個の変更された.rbファイル(app + libで30.7k挿入 / 12.8k削除;リポジトリ全体で6,238ファイル)にわたって、この侵食は避けられません。
まとめ:パッチラインスイープ(安定したファイルツリー、固定ベースライン)はベースラインの安定性のためのクリーンな計測器です。クロスメジャースイープは「新しいコードが定常診断を持っているか」(yes — v4.5.10までに15件)に有用ですが、その浮上カウントは新しい診断+リネームアーティファクトとして読まなければならず、リグレッションカウントではありません。浮上がジャンプしたとき、タグをdiffしてまずリネームを除外してください。
何が増加しているか — ルールと原因別
Section titled “何が増加しているか — ルールと原因別”浮上した各診断を最初に登場したタグまでトレースし、ソースを読むと、15件のv4.5.10セットの内訳は次のとおり:
| クラスタ | ルール | N | 原因 | 判定 |
|---|---|---|---|---|
signature_parser.rb | argument-type-mismatch | 3 | StringScanner#[]がシンボル名前付きキャプチャで呼ばれている(scanner[:key]); RigorのRBSはIntegerオーバーロードしか持たない | 偽陽性 — RBSギャップ |
account.rb | undefined-method | 1 | scope :duplicate_uris, -> { select(...).group(:uri) }内でRigorがselectをEnumerable#select(→ Array[String])に解決するため、.groupがundefined-methodになる | 誤推論 — ARスコープボディ |
block_domain_service.rb | undefined-method | 1 | return if @domain_block_event.nil?ガードの後の@domain_block_event.affected_local_accounts; ivarは依然としてnilと型付けされている | 誤推論 — ivar型付け |
cli/statuses.rb | undefined-method | 2 | ClassへのTable_name= — statuses_cli.rb → cli/statuses.rbリネームアーティファクト(§上記) | チャーンアーティファクト |
| ActivityPub ×3ファイル | flow.always-truthy-condition | 3 | create.rb / linked_data_signature.rb / link_details_extractor.rbのフローフォールディングが条件を定数と過剰主張 | 偽陽性 — フローフォールディング |
| CLI + ワーカー + モデル | possible-nil-receiver | 5 | ARクエリ結果 / アソシエーションがnilableと型付けされ、ガードなしで呼ばれている | サイトごとのトリアージが必要 |
最初登場トレース(浮上 0→1→3→5→10→13→14→15→15):
各ステップは古いコードのリグレッションではなく新しいコードです — media_cli / accounts_cliのnil-receiver(v4.0〜v4.1)、CLIリネームのtable_name=ペア(v4.2.7)、signature_parser + block_domain_service + with_recursiveクラスタ(v4.3.0-beta.1)、account.rbのgroup + 2件のフローフォールディングサイト(v4.3.0)、fasp/ワーカー + signed_request(v4.4.0)、interaction_policy_concern(v4.5.0)。flow.dead-assignmentがv4.1.15で登場しv4.3までにアップストリームでクリアされました — Rigorが捉え、Mastodonが修正した真のリファクタリング臭。lib/active_record/with_recursive.rbクラスタ(with_recursive! on Integer + フローフォールディングサイト)がv4.3.0で浮上しv4.4.0までに消えました。
増加の解釈:上昇はRigorの既知の精度ギャップに当たる新しいコードに支配されており、新しいバグではありません。15件のうち: 3件のargument-type-mismatchと3件のflow.always-truthy-conditionは完全な偽陽性; 2件はARシェイプの誤推論; 2件はリネームアーティファクト。候補として真の発見となりうるのは5件のpossible-nil-receiver警告だけで、それらもまだサイトごとのトリアージが必要です(rigor-baseline-reduceスキルの仕事)。したがってクロスメジャーの浮上曲線は、より多いコードがより多くの接触を意味するため、同じ有限のエンジン精度ギャップのセットとの接触でコードボリュームとともに増加します — もう一つのリグレッションカウントでない理由。
コールドキャッシュスポットチェック
Section titled “コールドキャッシュスポットチェック”v4.5.10でのコールド--no-cache --no-baseline実行がraw = 30(error ×9 / warning ×12 / info ×9)を確認 — パッチスイープのv4.5.10およびv0.1.8のノートと同一。共有キャッシュは何も隠していませんでした; 2つのスイープは絶対的な診断セットに合意します。
クロスバージョンの判定
Section titled “クロスバージョンの判定”- v3.5.19のベースラインはv4.5.10の診断の正確に半分をカバー(30件中15件)。古いMastodonにRigorを採用してベースラインをリフレッシュしないと、v4.5.10までに15件の診断が浮上します — ただし約2件はCLIリネームアーティファクトなので、真の定常診断増加は約13件。
- リネームの注意点は実在して測定可能。フリーズされたベースラインでメジャーアップグレードにまたがって実行するチームは、大きなリファクタリング(ファイル移動)後にベースラインを再生成すべきです — ちょうどADR-22 /
rigor-baseline-reduceスキルが想定する通りに。 - パースエラーのフロアは実在して設定で修正可能。ジェネレータの
.rbテンプレートを持つRailsプロジェクトはそれらをexclude:に入れる必要があります;rigor-project-initはRailsスタックにそのexcludeを出力すべきです(キューに追加のフォローアップ — 以下参照)。
これらのスイープが浮かび上がらせたフォローアップ
Section titled “これらのスイープが浮かび上がらせたフォローアップ”設定 / ツーリング
Section titled “設定 / ツーリング”rigor-project-initはRailsスタックに対して"**/lib/templates/**/*.rb"(またはより広いジェネレータテンプレートパス)を出力するexclude:に追加すべきです — パースエラーのフロアはジェネレータを持つすべてのRailsアプリで初回実行時の確実なペーパーカットになります。rigor-regression-sweepSKILL § “Phase 8”のパースエラーフロアの段落は、File.fnmatch?-FNM_PATHNAMEなし + 絶対パスマッチングルール(ベアなディレクトリ名はexclude:エントリーとして機能しない;組み込みexcludeの形式**/dir/**を使用する)を記載できます。
偽陽性 / 誤推論 — 解決TODOリスト
Section titled “偽陽性 / 誤推論 — 解決TODOリスト”クロスバージョン § “何が増加しているか”テーブルが4つのエンジン側の欠陥を分離しています。docs/CURRENT_WORK.md§ “未解決エンジニアリング項目” → “Mastodonクロスバージョンスイープ — FP発見事項”にTODOとして記録;ここにまとめ:
StringScanner#[]シンボルオーバーロード(偽陽性、3サイト)。scanner[:key]— Ruby 3.x以降で有効なシンボル名前付きキャプチャ引数 — は、RigorのRBSのStringScanner#[]が(Integer) -> String?しか持たないためcall.argument-type-mismatchを引き起こします。すでに追跡済み:CURRENT_WORK.md§ “Stdlib RBSカバレッジギャップパターン”が、まさにこのシグネチャを拡張するreferences/rbsブランチwiden-strscan-resolv-stdlib-sigsを挙げています。このスイープは経験的な確認です;修正はステージングされたアップストリームRBS PRです。- AR
scopeボディのメソッド解決(誤推論、1サイト)。scope :duplicate_uris, -> { select(...).group(:uri) }内でラムダのselfはモデルクラスです;selectはActiveRecord::Querying#select(→ リレーション)に解決すべきところをEnumerable#select(→Array[String])に解決するため、チェーンされた.groupがundefined-methodとして読まれます。ADR-26(ActiveRecord::Relation型付け)の経験的なケース — スイープ設定がrigor-activerecordプラグインを省略していることに注意。そのプラグインがモデルクラスのクエリサーフェスを型付けする予定の場所です。 - Ivarのnil-guard / ivarライト型付け(誤推論、1サイト)。
block_domain_service.rbがreturn if @domain_block_event.nil?ガードの後に@domain_block_event.affected_local_accountsを呼び出しますが、ivarはnilと型付けされています(nilableなpossible-nil-receiverではなくundefined-method ... for nil)。フローフォールディングギャップG2と同じファミリー(ivarの型はリテラルライトから取られ、リフレッシュされない)— ガード節はivarをナロートせず、ivarの非nil代入は推論に見えません。ivarナローイング / ivarライト推論の修正が必要。 - フローフォールディングの過剰主張(偽陽性、3サイト)。
activity/create.rb、linked_data_signature.rb、link_details_extractor.rbのflow.always-truthy-condition。すでに追跡済み:CURRENT_WORK.md§ “フローフォールディング — ループミューテーション追跡(ギャップG1 / G2)“とクラスタ4トリアージ。このスイープはクラスタがv3.5→v4.5ラインにわたって持続することを確認します。
5件のcall.possible-nil-receiver警告はエンジンのTODOとして記録されていません — 候補として真の発見であり、偽陽性バックログではなくサイトごとのトリアージ(rigor-baseline-reduce)に属します。
パッチラインスイープは~/repo/ruby/rigor-survey/_mastodon-sweep/(sweep.sh、tabulate.rb、再生成されたbaseline.yml、reports/<tag>.json; v0.1.8のレポートはreports-v0.1.8/として保存)にあります。クロスバージョンスイープは同じファイルレイアウトとv3.5.19のbaseline.ymlを持つ兄弟ディレクトリ_mastodon-major-sweep/にあります。
手順はrigor-regression-sweepスキルです。
© 2026 TypedDuck. Licensed under CC BY-SA 4.0.