Redmine 6.x regression sweep — baseline-drift over a release line
日付: 2026-05-21。Rigor: v0.1.9(master)。
対象: redmine/redmine、13タグ6.0.0→6.1.2。
Mastodon v4.5.x sweep(20260521-mastodon-v4.5-regression-sweep.md)に続く、rigor-regression-sweep手順の2回目の実行。経験的なコーパスを広げ、そして — Mastodonのフラットゼロの結果とは違って — 解剖すべき本物のベースライン突破イベントを生み出す。
セットアップ
Section titled “セットアップ”redmine/redmineのblobless clone。リリース順に13タグ:6.0.0 … 6.0.9(10パッチのシリーズ)に加えて6.1.0 6.1.1 6.1.2— つまりこの範囲はパッチ安定化期間と6.0 → 6.1のマイナー機能バンプの両方をまたぐ(SKILLのPhase 1ガイダンスに従い、純粋なパッチシリーズよりも機能をまたぐ範囲を優先する)。- 固定した設定。プロジェクト間の比較可能性のためMastodon sweepと同一:
paths: [app, lib]、exclude: [vendor, tmp]、severity_profile: lenient、signature_paths:→rigor-activesupport-core-extのsig/バンドル(絶対パス)。 6.0.0でのベースライン: 診断145件 / バケット59個。app + lib対象範囲:6.0.0で.rbファイル322件、6.1.2で331件。範囲全体で.rbファイル112件が変更された。
結果 — フラットな22、その後6.1.2で+6の突破
Section titled “結果 — フラットな22、その後6.1.2で+6の突破”| タグ | raw | silenced | surfaced |
|---|---|---|---|
| 6.0.0 … 6.1.1 | 144–145 | 122–123 | 22 |
| 6.1.2 | 145 | 117 | 28 |
説明すべきことが2つある: 一定の22と、6.1.2での+6。
一定の22 — パースエラー、ベースライン化不能
Section titled “一定の22 — パースエラー、ベースライン化不能”すべてのタグ — ベースラインタグ6.0.0自身を含む — で表面化した22件の診断はパースエラー(unexpected '<', ignoring it、unterminated string meets end of file、…)であり、22件すべてが1ファイルから来ている: lib/generators/redmine_plugin_model/templates/migration.rb。
そのファイルはRailsのジェネレータテンプレート — .rb拡張子を持つが実体はERBテンプレート(<%= … %>)であり、20260519-oss-library-survey.mdのサーベイ§8aのパターンである。
これらがベースラインタグで表面化するのは、パースエラーがruleを持たないからだ。そしてBaseline.from_diagnosticsはqualified_ruleとpathの両方を持つ診断のみをバケットに入れる — よってルールを持たない診断はベースラインに一度も記録されず、Baseline#filterは常にそれを通過させる(unkeyableセット)。これは方法論上の発見である: ベースライン機構はパースエラー / 内部アナライザーエラーに対して盲点を持つ。修正は設定側 — ジェネレータテンプレートのディレクトリをexclude:する — であり、rigor-regression-sweepおよびrigor-project-init SKILLはそう述べるべきである。
6.1.2での+6 — FPパターンのチャーンによるフォルスポジティブ
Section titled “6.1.2での+6 — FPパターンのチャーンによるフォルスポジティブ”6.1.1 → 6.1.2は新規のcall.undefined-method診断を6件、すべてapp/models/issue.rb内で表面化した:
issue.rb:1763 undefined method `user' for nilissue.rb:1799 undefined method `user' for nilissue.rb:2008 undefined method `user' for nilissue.rb:2008 undefined method `notes' for nilissue.rb:2009 undefined method `private_notes' for nilissue.rb:2019 undefined method `notes_and_details_empty?' for nilどれもがif @current_journal(または@current_journal && …)ガードの内側での@current_journal.METHODである:
if @current_journal @copied_from.init_journal(@current_journal.user) # flaggedendこれらはフォルスポジティブである。コードは明示的にインスタンス変数をガードしているが、Rigorは真偽値のif @ivarガードを通じてインスタンス変数を非nilにナローイングしないため、@current_journalは帰結節の内側でもJournal | nilのままであり、それに対するすべてのメソッド呼び出しが… for nilを報告する。これはクラスタ4のG2 ivarナローイングギャップ(20260521-mastodon-cluster4-flow-folding-triage.md)と同じ系統である。
これらが6.1.2で — それより早くではなく — 表面化したのは、Redmineの6.1開発がガードされた@current_journalの呼び出しサイトをissue.rbにさらに追加し、(app/models/issue.rb, call.undefined-method)バケットをその6.0.0ベースラインカウントを超えて押し上げたからだ。その後WD4のALL-or-NOTHINGがバケット全体を表面化させる。
- このsweepは本物のベースラインドリフトイベントを検出した — Mastodonのフラットゼロとは違って。ドリフト機構は機能している:
6.0.0でRigorを採用したプロジェクトは、6.1.2でCIがクリーンから「issue.rb内に新規診断6件」へと変わるのを目にしただろう。 - しかしこの突破はバグではなくフォルスポジティブである。この実験は、ベースラインドリフトがFPパターンの蓄積も捕まえることを示している: 通常の開発が既知のフォルスポジティブの形(ガードされたivarアクセス)に一致するコードをさらに追加するにつれ、本物の欠陥が一切持ち込まれていなくてもバケットが突破される。これは
severity_profile: lenientデフォルトを支持する論拠(6件がerrorなのはcall.undefined-methodがlenient下でもerrorのままだからにすぎず、いずれにせよ表面化する)であり、また下記のivarナローイングのエンジン修正を支持する論拠でもある。 - エンジンギャップが表面化した — 真偽値ガードを通じたivarナローイング。
if @ivar; @ivar.methodは@ivarを非nilにナローイングしない。具体的で再発するフォルスポジティブの源。キュー済み(下記参照)。 - パースエラーはベースラインの盲点である。ルールを持たない診断はベースラインを迂回し、永遠に表面化する。ジェネレータの
.rbテンプレートが一般的な源である。それらはexclude:せよ。
トリアージヒューリスティックのクロスチェック(ADR-23)
Section titled “トリアージヒューリスティックのクロスチェック(ADR-23)”6.0.0に対しASバンドルなしでrigor triageを実行(診断320件) — 2つ目のプロジェクトでヒューリスティックカタログを確認するため:
- H1
activesupport-core-ext— 診断155件、html_safe×94 wrap×25 deep_dup×5 …。アクションはplugins:の有効化を正しく挙げている(ADR-25のH1修正は今サイクルで着地した)。正しい。 - H4
activerecord-relation-misinference— 4件、rigor-activerecordを挙げる。正しい。 - H5
systemic-file-cluster— 22件のパースエラーのファイルlib/generators/redmine_plugin_model/templates/migration.rbを正確にピンポイントする。正しい。 - H6
genuine-bugs—call.argument-type-mismatchが3件。妥当。
ヒューリスティックカタログは、構造的に異なる2つ目のプロジェクトでも持ちこたえている。
フォローアップ
Section titled “フォローアップ”- エンジン —
if @ivar/@ivar && …の真偽値ガードを通じたivarナローイング。再発するフォルスポジティブ。クラスタ4のG2と同じサーフェス(control-flow-analysis.md§「mutation effects」 / ナローイング)。キュー済み。 - SKILL —
rigor-regression-sweep(およびrigor-project-init)は、ジェネレータの.rbテンプレートがベースライン化不能なパースエラーを生み、exclude:に属することを記すべきである。
~/repo/ruby/rigor-survey/_redmine-sweep/にsweep.sh、
tabulate.rb、rigor-no-as.yml、固定したbaseline.yml、
reports/<tag>.jsonが置かれている。
© 2026 TypedDuck. Licensed under CC BY-SA 4.0.