コンテンツにスキップ

Redmine 6.x regression sweep — baseline-drift over a release line

日付: 2026-05-21。Rigor: v0.1.9(master)。 対象: redmine/redmine、13タグ6.0.06.1.2

Mastodon v4.5.x sweep(20260521-mastodon-v4.5-regression-sweep.md)に続く、rigor-regression-sweep手順の2回目の実行。経験的なコーパスを広げ、そして — Mastodonのフラットゼロの結果とは違って — 解剖すべき本物のベースライン突破イベントを生み出す。

  • 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: lenientsignature_paths:rigor-activesupport-core-extsig/バンドル(絶対パス)。
  • 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の突破”
タグrawsilencedsurfaced
6.0.0 … 6.1.1144–145122–12322
6.1.214511728

説明すべきことが2つある: 一定の22と、6.1.2での+6

一定の22 — パースエラー、ベースライン化不能

Section titled “一定の22 — パースエラー、ベースライン化不能”

すべてのタグ — ベースラインタグ6.0.0自身を含む — で表面化した22件の診断はパースエラーunexpected '<', ignoring itunterminated 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_diagnosticsqualified_rulepathの両方を持つ診断のみをバケットに入れる — よってルールを持たない診断はベースラインに一度も記録されず、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 nil
issue.rb:1799 undefined method `user' for nil
issue.rb:2008 undefined method `user' for nil
issue.rb:2008 undefined method `notes' for nil
issue.rb:2009 undefined method `private_notes' for nil
issue.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) # flagged
end

これらはフォルスポジティブである。コードは明示的にインスタンス変数をガードしているが、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がバケット全体を表面化させる。

  1. このsweepは本物のベースラインドリフトイベントを検出した — Mastodonのフラットゼロとは違って。ドリフト機構は機能している: 6.0.0でRigorを採用したプロジェクトは、6.1.2でCIがクリーンから「issue.rb内に新規診断6件」へと変わるのを目にしただろう。
  2. しかしこの突破はバグではなくフォルスポジティブである。この実験は、ベースラインドリフトがFPパターンの蓄積も捕まえることを示している: 通常の開発が既知のフォルスポジティブの形(ガードされたivarアクセス)に一致するコードをさらに追加するにつれ、本物の欠陥が一切持ち込まれていなくてもバケットが突破される。これはseverity_profile: lenientデフォルトを支持する論拠(6件がerrorなのはcall.undefined-methodlenient下でもerrorのままだからにすぎず、いずれにせよ表面化する)であり、また下記のivarナローイングのエンジン修正を支持する論拠でもある。
  3. エンジンギャップが表面化した — 真偽値ガードを通じたivarナローイングif @ivar; @ivar.method@ivarを非nilにナローイングしない。具体的で再発するフォルスポジティブの源。キュー済み(下記参照)。
  4. パースエラーはベースラインの盲点である。ルールを持たない診断はベースラインを迂回し、永遠に表面化する。ジェネレータの.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-bugscall.argument-type-mismatchが3件。妥当。

ヒューリスティックカタログは、構造的に異なる2つ目のプロジェクトでも持ちこたえている。

  • エンジンif @ivar / @ivar && …の真偽値ガードを通じたivarナローイング。再発するフォルスポジティブ。クラスタ4のG2と同じサーフェス(control-flow-analysis.md §「mutation effects」 / ナローイング)。キュー済み。
  • SKILLrigor-regression-sweep(およびrigor-project-init)は、ジェネレータの.rbテンプレートがベースライン化不能なパースエラーを生み、exclude:に属することを記すべきである。

~/repo/ruby/rigor-survey/_redmine-sweep/sweep.shtabulate.rbrigor-no-as.yml、固定したbaseline.ymlreports/<tag>.jsonが置かれている。

© 2026 TypedDuck. Licensed under CC BY-SA 4.0.