コンテンツにスキップ

Mastodonリグレッションスイープ — Rigor v0.1.9での再実行

日時: 2026-05-23。Rigor: v0.1.9(master[Unreleased])。 対象: mastodon/mastodon

2つのスイープ:

  1. パッチライン — 16タグv4.5.0-beta.1v4.5.102026-05-21 v0.1.8スイープを現在のエンジンで再実行。
  2. クロスバージョン — 5つのマイナー/メジャーリリースラインにまたがる9タグv3.5.19v4.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を実行。

  • mastodon/mastodonの同じbloblessクローン、同じ16タグをリリース順(v4.5.0-beta.1 … v4.5.10)で — すべての存在を確認済み。
  • v0.1.8実行と同じ固定設定(全タグで同一を保持): paths: [app, lib]exclude: [vendor, tmp]severity_profile: lenientsignature_paths:rigor-activesupport-core-extsig/バンドル(絶対パス)。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.130300
v4.5.0-beta.230300
v4.5.0-rc.1 … -rc.330300
v4.5.030300
v4.5.1 … v4.5.1030300

全タグ: 浮上 = 0raw = 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 ×9call.undefined-method ×9
warning ×12call.possible-nil-receiver ×9、call.argument-type-mismatch ×3
info ×9flow.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エンジンでも変化なし。

  1. v0.1.8 → v0.1.9のエンジン変更はこのコーパスで診断上中立。ベータ1のベースライン、タグごとの浮上曲線、v4.5.10のコールドrawの構成は、2つのエンジンバージョン間でまったく同一です。v0.1.8とv0.1.9の間に出荷されたものは、固定設定下のMastodonのapp + libスコープで診断を1件も追加・削除・変更しませんでした — リリースラインにとって有用なno-regressionシグナル。
  2. ADR-22のacknowledgeモードは経験的に検証済みのままv4.5.0-beta.1でRigorを採用したプロジェクトは、v4.5.x全ラインを通してベースラインメンテナンスなし・CI偽陽性なしで乗り越えられます — そしてこの結論は1つではなく2つのエンジンバージョンにわたって成立します。
  3. (file, rule, count)ベースラインはエンジンバージョン間でロバスト。v0.1.8で生成されたベースラインとv0.1.9で生成されたベースラインは同じ25バケットをカバーし、パッチバンプ間でルールIDモードのキーイングに何もドリフトしませんでした。
  • この再実行は元の実行のすべての制限を引き継ぎます。リリースタグはスペックゲート後の母集団であるため、ライン全体での浮上 = 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のもの)。

最初の実行が失敗しました: rigorチェックアウトのvendor/bundleが古いRuby ABIに対してコンパイルされたネイティブ拡張(jsonprismrbs)を保持していました — 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”に従い、これはフィーチャースパニングのリリースタグ範囲です — ベースラインがすでにカバーしていない、新しいリリースコードが定常診断を追加するかどうかを測定するもので、パッチラインスイープのベースライン安定性とは別の問いです。

  • 同じ固定設定形式; 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:に追加すると、以下の曲線がきれいになります。

タグファイル数rawサイレンス済み浮上
v3.5.1987522220
v4.0.1595523221
v4.1.1596125223
v4.2.7102225205
v4.3.0-beta.11112281810
v4.3.01096311813
v4.4.01188291514
v4.5.01218301515
v4.5.101219301515

ゼロフラットのパッチラインとは異なり、浮上は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つのことが同時に動きます:

  1. 真に新しい定常診断 — 新しいファイル / 新しいコードパス(fasp/ワーカー、interaction_policy_concernsignature_parser)が診断を持っています。上昇の大部分。
  2. リネームアーティファクト。ベースラインは(file, rule, count)でキー付けされます。コミットb6b4ea4c“Move the mastodon/*_cli files to mastodon/cli/*”、#24139)がすべてのCLIファイルをリネームしました — lib/mastodon/statuses_cli.rblib/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.rbargument-type-mismatch3StringScanner#[]がシンボル名前付きキャプチャで呼ばれている(scanner[:key]); RigorのRBSはIntegerオーバーロードしか持たない偽陽性 — RBSギャップ
account.rbundefined-method1scope :duplicate_uris, -> { select(...).group(:uri) }内でRigorがselectEnumerable#select(→ Array[String])に解決するため、.groupがundefined-methodになる誤推論 — ARスコープボディ
block_domain_service.rbundefined-method1return if @domain_block_event.nil?ガードの@domain_block_event.affected_local_accounts; ivarは依然としてnilと型付けされている誤推論 — ivar型付け
cli/statuses.rbundefined-method2ClassへのTable_name= — statuses_cli.rbcli/statuses.rbリネームアーティファクト(§上記)チャーンアーティファクト
ActivityPub ×3ファイルflow.always-truthy-condition3create.rb / linked_data_signature.rb / link_details_extractor.rbのフローフォールディングが条件を定数と過剰主張偽陽性 — フローフォールディング
CLI + ワーカー + モデルpossible-nil-receiver5ARクエリ結果 / アソシエーションが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.rbgroup + 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つのスイープは絶対的な診断セットに合意します。

  1. v3.5.19のベースラインはv4.5.10の診断の正確に半分をカバー(30件中15件)。古いMastodonにRigorを採用してベースラインをリフレッシュしないと、v4.5.10までに15件の診断が浮上します — ただし約2件はCLIリネームアーティファクトなので、真の定常診断増加は約13件。
  2. リネームの注意点は実在して測定可能。フリーズされたベースラインでメジャーアップグレードにまたがって実行するチームは、大きなリファクタリング(ファイル移動)後にベースラインを再生成すべきです — ちょうどADR-22 / rigor-baseline-reduceスキルが想定する通りに。
  3. パースエラーのフロアは実在して設定で修正可能。ジェネレータの.rbテンプレートを持つRailsプロジェクトはそれらをexclude:に入れる必要があります; rigor-project-initはRailsスタックにそのexcludeを出力すべきです(キューに追加のフォローアップ — 以下参照)。

これらのスイープが浮かび上がらせたフォローアップ

Section titled “これらのスイープが浮かび上がらせたフォローアップ”
  • rigor-project-initはRailsスタックに対して"**/lib/templates/**/*.rb"(またはより広いジェネレータテンプレートパス)を出力するexclude:に追加すべきです — パースエラーのフロアはジェネレータを持つすべてのRailsアプリで初回実行時の確実なペーパーカットになります。
  • rigor-regression-sweep SKILL § “Phase 8”のパースエラーフロアの段落は、File.fnmatch?-FNM_PATHNAMEなし + 絶対パスマッチングルール(ベアなディレクトリ名はexclude:エントリーとして機能しない;組み込みexcludeの形式**/dir/**を使用する)を記載できます。

偽陽性 / 誤推論 — 解決TODOリスト

Section titled “偽陽性 / 誤推論 — 解決TODOリスト”

クロスバージョン § “何が増加しているか”テーブルが4つのエンジン側の欠陥を分離しています。docs/CURRENT_WORK.md§ “未解決エンジニアリング項目” → “Mastodonクロスバージョンスイープ — FP発見事項”にTODOとして記録;ここにまとめ:

  1. 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です。
  2. ARscopeボディのメソッド解決(誤推論、1サイト)。scope :duplicate_uris, -> { select(...).group(:uri) }内でラムダのselfはモデルクラスです; selectActiveRecord::Querying#select(→ リレーション)に解決すべきところをEnumerable#select(→ Array[String])に解決するため、チェーンされた.groupundefined-methodとして読まれます。ADR-26ActiveRecord::Relation型付け)の経験的なケース — スイープ設定がrigor-activerecordプラグインを省略していることに注意。そのプラグインがモデルクラスのクエリサーフェスを型付けする予定の場所です。
  3. Ivarのnil-guard / ivarライト型付け(誤推論、1サイト)。block_domain_service.rbreturn 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ライト推論の修正が必要。
  4. フローフォールディングの過剰主張(偽陽性、3サイト)。activity/create.rblinked_data_signature.rblink_details_extractor.rbflow.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.shtabulate.rb、再生成されたbaseline.ymlreports/<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.