diff --git a/.github/workflows/build-opencv.yml b/.github/workflows/build-opencv.yml index 137b6ce..ee9b3a5 100644 --- a/.github/workflows/build-opencv.yml +++ b/.github/workflows/build-opencv.yml @@ -124,7 +124,7 @@ jobs: - name: Set up Emscripten if: matrix.platform == 'web-wasm' - uses: mymindstorm/setup-emsdk@v14 + uses: mymindstorm/setup-emsdk@v16 with: version: ${{ steps.emver.outputs.version }} diff --git a/.github/workflows/ci-native.yml b/.github/workflows/ci-native.yml index 5481f6e..6c17cd2 100644 --- a/.github/workflows/ci-native.yml +++ b/.github/workflows/ci-native.yml @@ -375,7 +375,7 @@ jobs: - name: Set up Emscripten if: matrix.platform == 'web-wasm' - uses: mymindstorm/setup-emsdk@v14 + uses: mymindstorm/setup-emsdk@v16 with: version: ${{ steps.emver.outputs.version }} diff --git a/.github/workflows/ci-unity.yml b/.github/workflows/ci-unity.yml index 12ce80d..d4d07d4 100644 --- a/.github/workflows/ci-unity.yml +++ b/.github/workflows/ci-unity.yml @@ -125,7 +125,7 @@ jobs: - name: Set up Emscripten if: matrix.platform == 'web-wasm' - uses: mymindstorm/setup-emsdk@v14 + uses: mymindstorm/setup-emsdk@v16 with: version: ${{ steps.emver.outputs.version }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f108b0c..632bcfa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -119,7 +119,7 @@ jobs: - name: Set up Emscripten if: matrix.platform == 'web-wasm' - uses: mymindstorm/setup-emsdk@v14 + uses: mymindstorm/setup-emsdk@v16 with: version: ${{ steps.emver.outputs.version }} diff --git a/CLAUDE.md b/CLAUDE.md index 94dda0a..72f90ec 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -76,10 +76,10 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co | `./tools/dev.ps1 test-managed` | L3 のみ。**solution の全テストプロジェクトを回す** —— `CvUnity.Tests.Managed` が P/Invoke 越しに実物の DLL を叩く **196 件**(M7a で `AllocationTests` が加わり 181 → 185、M7c で `DnnInferenceTests` が加わり 185 → 195、レビューの M6 で forward の OpenCV エラー経路を実証するテストが 1 件加わり 196 になった)、`Ocvu.Generator.Tests` が spec と生成器を見る **116 件**(M5 で新設、106 件。M7b で profile 分岐のテストが加わり 113 件、最終レビューの C-1 で `LibraryName` の写しを見る 3 件が加わり 116 件になった)。**件数を書いてあるのはこの行だけである** —— 他所に写すと、テストを 1 件足した瞬間にそちらだけが嘘になる(M5 で実際に 4 箇所が同時に古くなった) | 約 11 秒(**44 件だけだった頃の値**) | | `./tools/dev.ps1 test-asan` | L2(AddressSanitizer) | 約 18 秒(増分。2026-08-28 実測。M1 時点の約 11 秒より伸びているが、原因は未特定——増えたのは L1 側で計測済みの再コンパイル対象と同じファイル群で、M3 固有の変更ではない) | | `./tools/dev.ps1 test-managed-probe` | **CI 専用**。L3 のクラッシュ・ハングプローブ | 約 50 秒(segfault 6 秒 + hang 36 秒) | -| `./tools/dev.ps1 test-unity-editmode` | L4(Unity EditMode、Mono、**58 件**。`-testCategory '!Graphics'` で `test-unity-graphics` 側のテストを除外する) | 約 27 秒(増分。2026-08-28 実測。**Unity 6000.0.82f1・EditMode 10 件のときの値。** その後 M3.5 で 16 件、M4 で 33 件、M5 で 34 件、2026-09 の API 拡張で 48 件、M7a で 53 件、M7b で `ProfileGatingTests`(4 件)が加わり 57 件になったが所要時間は取り直していない) | +| `./tools/dev.ps1 test-unity-editmode` | L4(Unity EditMode、Mono、**59 件**。`-testCategory '!Graphics'` で `test-unity-graphics` 側のテストを除外する) | 約 27 秒(増分。2026-08-28 実測。**Unity 6000.0.82f1・EditMode 10 件のときの値。** その後 M3.5 で 16 件、M4 で 33 件、M5 で 34 件、2026-09 の API 拡張で 48 件、M7a で 53 件、M7b で `ProfileGatingTests`(4 件)が加わり 57 件になったが所要時間は取り直していない。**59 件は 2026-09-10 に実測し直した値**(`unity-editmode.xml` の `testcasecount="59"`)。旧「58 件」は M7 squash(`be5615f`)の時点では正しかった——`tests/UnityProject/Assets/Tests/EditMode/*.cs` の `[Test]`/`[UnityTest]` 属性行を数えると `be5615f` で 65 件、うち Graphics カテゴリ 7 件を除いて 58 件。差の 1 件は M7c(`e1b0930`、"dnn を opt-in profile として足す")が `ProfileGatingTests.cs` に足した `TheDnnPublicApiAssemblyIsAlsoAbsentWithoutItsDefine`(同ファイルの `[Test]` 数が 5→6)で、同じ数え方で `e1b0930` は 66 件、Graphics 7 件を除いて 59 件になる——この行を更新する commit がその後に続かなかっただけである) | | `./tools/dev.ps1 test-unity-player` | L5(Unity IL2CPP Player のビルドと実行、**39 件**。`-nographics` で走るので GPU に依る経路は含まない。**M7a で `RenderTextureChecks` の PlayMode 側の対(`RenderTexturePlayerTests`)を足し、35 → 39 になった**) | 約 54 秒(増分・キャッシュ温状態。2026-08-28 実測。cold 実測はまだ無く、roadmap の想定は 5〜20 分。**Unity 6000.0.82f1・10 件での値**) | | `./tools/dev.ps1 test-unity-graphics` | **M7a。ローカル専用**。`RenderTexture` を使う GPU 依存の経路(`GraphicsTests` / `GraphicsBenchmarkRunner`)を EditMode で検証する。`-nographics` を**付けない**(`-nographics` の下では `graphicsDeviceType` が `Null` になり `RenderTexture.Create()` が true を返しつつ画素が読めなくなるため、実測)。**`ci-unity.yml` からは呼ばれない** —— このレーンが赤くても merge は止まらない。CI から見えないテストの一覧は `tests/UnityProject/Assets/Tests/EditMode/CiVisibilityTests.cs` が名指しで固定している(**一覧は同ファイルの `ExpectedGraphicsOnlyTests` が持つ** —— 本数をここに写すと、1 件足した日にこの行だけが嘘になる) | 未計測 | -| `./tools/dev.ps1 test-unity-tarball` | **UPM tarball の導入検証。** tarball だけを指した使い捨ての Unity プロジェクトを作り、そこで EditMode を走らせる。**`-PluginSource` に他 platform の plugin 木(';' 区切り)を渡すと全部入りとして固めてから検証する** —— 渡さなければ従来どおり 1 platform 分で走り、**黙って全部入りのふりはしない** | 約 3 分(2026-08-28 実測。Library/ を持って行かないので Unity が import からやり直す。**Unity 6000.0.82f1・1 platform でのもの**)。**6 platform の全部入りは 2026-09-03 に実測** —— `release.yml` の空撃ちが作った実物の tarball を展開して材料にし、`native plugins present: 6` / `34 passed` / exit 0(**所要時間は取っていない**)| +| `./tools/dev.ps1 test-unity-tarball` | **UPM tarball の導入検証。** tarball だけを指した使い捨ての Unity プロジェクトを作り、そこで EditMode を走らせる。`-testCategory '!Graphics'` で `test-unity-graphics` 側のテストを除外する(`Test-UnityEditMode` と同じ `$script:UnityGraphicsExclusionCategory` を使う——2026-09-10 まで直書きのコピーで抜けており、GPU に依るテストが「スキップ」ではなく「失敗」していた)。**`-PluginSource` に他 platform の plugin 木(';' 区切り)を渡すと全部入りとして固めてから検証する** —— 渡さなければ従来どおり 1 platform 分で走り、**黙って全部入りのふりはしない** | 約 3 分(2026-08-28 実測。Library/ を持って行かないので Unity が import からやり直す。**Unity 6000.0.82f1・1 platform でのもの**)。**6 platform の全部入りは 2026-09-03 に実測** —— `release.yml` の空撃ちが作った実物の tarball を展開して材料にし、`native plugins present: 6` / `34 passed` / exit 0(**所要時間は取っていない**)。**2026-09-10 に Graphics カテゴリの除外を足した後で実測し直した** —— 除外前は `66 passed=60 failed=6`、除外後は `59 passed` で exit 0(`unity-tarball.xml` の `testcasecount`)| | `./tools/dev.ps1 test-unity-web` | **M6。** WebGL の Player を建て、**ブラウザで走らせる**(Playwright + headless Chromium)。先に `assert-emscripten-version.ps1` が **Unity 同梱の Emscripten を対応表と突き合わせる** —— **このレーンに置くのが正しい**(WebGL の Player を建てられる時点で Unity と WebGL 支援は必ず在るので、「道具が無いから飛ばす」経路が構造的に生まれない)。**stripping は有効のまま**にする(無効にすると到達性テストが確かめたいことを確かめられない) | **所要時間は取っていない。** 通した実績はある(ローカル・CI とも `failed=0`)。**`passed` も `reachable` も数を写さない** —— `passed` は共有本体 `AbiSurfaceChecks` の検査数(`tools/run-web-e2e.ps1` が数えて**完全一致**を要求する)、`reachable` は spec の entry 数で決まる。**写すと、検査や関数を 1 つ足した日にこの行だけが嘘になる**(実際 8 -> 21 で踏んだ) | | `./tools/dev.ps1 benchmark` | **M7a。** `test-unity-player` と `test-unity-graphics` を順に走らせ、両方の結果 XML から `OCVU_BENCH:` 行(`TestContext.WriteLine` が結果 XML の `` に入れたもの)を集めて `artifacts/benchmarks/latest.json` へ書く。**時間を判定しない** —— 落ちるのは「測れなかったとき」(0 マイクロ秒)だけで、遅い・速いでは落ちない(設計 D1)。数字の読み方は [性能](docs/performance.md) にまとめてある。**Unity がある唯一のこのマシンでは、このコマンドは現状完走しない** —— 内部で呼ぶ `test-unity-player` が後始末段階(`Stop-UnityTestPlayers` 内の `Get-CimInstance`)でハングする既知の欠陥を踏むため(詳細は `docs/roadmap.md` の M7a の判定「穴を隠さず書く」の項)。数字は、ハングしたプロセスを止めたうえで `run-benchmarks.ps1` を直接叩いて得た | 未計測(内部で呼ぶ 2 レーンの合計) | | `./tools/dev.ps1 clean` | `build/` を削除 | — | diff --git a/tests/UnityProject/Assets/Tests/EditMode/CiVisibilityTests.cs b/tests/UnityProject/Assets/Tests/EditMode/CiVisibilityTests.cs index 54a1eae..a585c2f 100644 --- a/tests/UnityProject/Assets/Tests/EditMode/CiVisibilityTests.cs +++ b/tests/UnityProject/Assets/Tests/EditMode/CiVisibilityTests.cs @@ -7,8 +7,10 @@ /// 台帳として名指しで固定する(M7a Task 2 のレビュー指摘)。 /// /// **`Graphics` と `!Graphics` は補集合なので、実行時の和集合は常に完全である。** -/// `test-unity-editmode` が `-testCategory '!Graphics'`、`test-unity-graphics` -/// が `-testCategory 'Graphics'` で走る限り、振り分け自体に穴は無い。 +/// `test-unity-editmode` と `test-unity-tarball` が `-testCategory '!Graphics'`、 +/// `test-unity-graphics` が `-testCategory 'Graphics'` で走る限り、振り分け +/// 自体に穴は無い(`!Graphics` 側が 2 レーンに増えても、補集合の性質は +/// 変わらない)。 /// /// **本当の穴は「一方のレーン(graphics)が CI に配線されていない」ことである。** /// `test-unity-graphics` はローカル専用で、`ci-unity.yml` からは呼ばれない。 @@ -24,9 +26,9 @@ /// **走査するのはこの assembly(EditMode)だけである。** 他の test /// assembly に `[Category("Graphics")]` が付いても、ここは気づかない —— /// **それでこの検査の目的は満たされる。** カテゴリで振り分けているのは -/// EditMode のレーンだけで(`test-unity-editmode` が `!Graphics`、 -/// `test-unity-graphics` が `Graphics`)、PlayMode / Standalone のレーンは -/// `-testCategory` を渡さない。つまり **他所でカテゴリを付けても、その +/// EditMode のレーンだけで(`test-unity-editmode` と `test-unity-tarball` が +/// `!Graphics`、`test-unity-graphics` が `Graphics`)、PlayMode / Standalone +/// のレーンは `-testCategory` を渡さない。つまり **他所でカテゴリを付けても、その /// テストは CI から消えない。** 消えるのはここに在るものだけなので、 /// 台帳もここだけを見る。**振り分けの前提が変われば、この段は嘘になる。** /// diff --git a/tools/dev.ps1 b/tools/dev.ps1 index d82a55d..7100109 100644 --- a/tools/dev.ps1 +++ b/tools/dev.ps1 @@ -557,6 +557,24 @@ $script:GatingTestNames = @( 'PluginGatingTests.EachPluginIsEnabledOnlyForItsOwnStandaloneTarget' ) +<# + GraphicsTests / GraphicsBenchmarkRunner(M7a Task 2、GPU に依る検査)を + 除外する -testCategory の値。**正本はここ 1 箇所。** + + -nographics の下では graphicsDeviceType が Null になり、GL.Clear の + 直後の ReadPixels が実際には描画しないまま 205,205,205 を返す + (実測、2026-09-05)。GPU に依る検査は test-unity-graphics に分けて + あるので、-nographics で EditMode を走らせるレーン(Test-UnityEditMode / + Test-UnityTarball)はどちらもこれを除外しないと、GraphicsTests を + 足しただけで恒久的に赤くなる。 + + 文字列として 2 度書かない —— tools/tests/OpenCvConfig.Tests.ps1 が + ci-unity.yml の customParameters とこの値を突き合わせるので、直書きの + コピーを増やすとそちらの検査から外れる(実際に Test-UnityTarball に + 直書きしたコピーができ、どこにも縛られていなかった。2026-09-10)。 +#> +$script:UnityGraphicsExclusionCategory = '!Graphics' + function Sync-AllPlatformsMarker { param([Parameter(Mandatory)][string] $ProjectPath) @@ -589,18 +607,15 @@ function Test-UnityEditMode { # -batchmode -nographics は CI とローカルで同じ条件にするため常に付ける。 # - # -testCategory '!Graphics' は GraphicsTests(M7a Task 2)を除外する。 - # -nographics の下では graphicsDeviceType が Null になり、GL.Clear / - # ReadPixels が実際には描画しないまま 205,205,205 を返す(実測、 - # 2026-09-05)。**GPU に依る検査は test-unity-graphics に分けてある** - # —— ここで除外しないと、GraphicsTests を足しただけでこのレーンが - # 恒久的に赤くなる。 + # -testCategory は GPU に依る検査(GraphicsTests / GraphicsBenchmarkRunner) + # を除外する。理由と正本は $script:UnityGraphicsExclusionCategory の + # 定義側に書いてある。 $unityArgs = @( '-projectPath', $project, '-runTests', '-testPlatform', 'EditMode', '-testResults', $results, '-logFile', $log, '-batchmode', '-nographics', - '-testCategory', '!Graphics' + '-testCategory', $script:UnityGraphicsExclusionCategory ) $proc = Start-Process -FilePath $unity -ArgumentList $unityArgs -Wait -PassThru -NoNewWindow $exit = $proc.ExitCode @@ -859,11 +874,16 @@ function Test-UnityTarball { $results = Join-Path $ResultsDir 'unity-tarball.xml' $log = Join-Path $ResultsDir 'unity-tarball.log' + # -testCategory は Test-UnityEditMode と同じ定義を使う + # ($script:UnityGraphicsExclusionCategory。理由と経緯はその + # 定義側にある)。このレーンも -testPlatform EditMode で走るので + # 同じ理由が当てはまる。 $unityArgs = @( '-projectPath', $project, '-runTests', '-testPlatform', 'EditMode', '-testResults', $results, '-logFile', $log, - '-batchmode', '-nographics' + '-batchmode', '-nographics', + '-testCategory', $script:UnityGraphicsExclusionCategory ) <# タイムアウトを付ける。CLAUDE.md の不変条件「テストは必ずタイムアウト diff --git a/tools/tests/OpenCvConfig.Tests.ps1 b/tools/tests/OpenCvConfig.Tests.ps1 index 4441914..76984b8 100644 --- a/tools/tests/OpenCvConfig.Tests.ps1 +++ b/tools/tests/OpenCvConfig.Tests.ps1 @@ -992,13 +992,13 @@ if ($markerName) { # --- ci-unity の EditMode レーンが、ローカルの -testCategory 除外と一致すること --- # -# tools/dev.ps1 の Test-UnityEditMode は GraphicsTests / GraphicsBenchmarkRunner -# (M7a Task 2、GPU に依る検査)を -testCategory '!Graphics' で除外する。 -# -nographics の下では graphicsDeviceType が Null になり、GL.Clear の直後の -# ReadPixels が実際には描画しないまま 205,205,205 を返す(実測、2026-09-05)。 -# GraphicsChecks.AGraphicsDeviceIsPresent は GPU が無ければ skip ではなく -# fail する設計なので、この除外を欠いたまま Unity を起動すると本物の欠陥として -# 落ちる。 +# tools/dev.ps1 は GraphicsTests / GraphicsBenchmarkRunner(M7a Task 2、GPU に +# 依る検査)を除外する値を $script:UnityGraphicsExclusionCategory 1 箇所に +# 持つ(定義側の docstring に理由がある)。-nographics で EditMode を走らせる +# レーン(Test-UnityEditMode と Test-UnityTarball)は両方ともこれを使う +# —— **直書きのコピーを許さない。** 2026-09-10 に実際に Test-UnityTarball が +# 直書きのコピーを持ち、どこからも縛られていなかった(この検査は +# Test-UnityEditMode しか見ていなかった)。 # # ci-unity.yml は「CI はローカルと同一のコマンドを呼ぶ」の意図的な例外 # (game-ci が Unity を起動し、tools/dev.ps1 ではない)なので、この 2 つの @@ -1014,22 +1014,72 @@ if ($markerName) { # 変わらず 1 のままになる(PluginGatingTests の合図名と同じ形)。 $devPs1Raw = Get-Content -LiteralPath (Join-Path $repoRoot 'tools/dev.ps1') -Raw -# Test-UnityGraphics にも '-testCategory' が在る(値は 'Graphics'、 -# -nographics を渡さない側)ので、関数本体を名前で切り出してから読む。 -# このファイルのトップレベル関数はすべて列 0 の '}' で閉じる規約 -# (tools/dev.ps1 の他の関数と同じ)なので、それを終端として使う。 -$editModeFnMatch = [regex]::Match($devPs1Raw, '(?ms)^function Test-UnityEditMode \{.*?^\}') -Assert-That $editModeFnMatch.Success ` - 'tools/dev.ps1 から Test-UnityEditMode 関数を切り出せる (切り出せなければ以下は空振りする)' +# 正本は $script:UnityGraphicsExclusionCategory の定義そのもの +# (関数本体の中の文字列ではない)。 +$exclusionDefMatches = [regex]::Matches($devPs1Raw, + "(?m)^\s*\`$script:UnityGraphicsExclusionCategory\s*=\s*'(?[^']+)'\s*`$") +Assert-That ($exclusionDefMatches.Count -eq 1) ` + "tools/dev.ps1 defines `$script:UnityGraphicsExclusionCategory exactly once (saw $($exclusionDefMatches.Count); 読み取れなければ以下は空振りする)" $localCategory = $null -if ($editModeFnMatch.Success) { - $localCatMatch = [regex]::Match($editModeFnMatch.Value, "'-testCategory',\s*'(?[^']+)'") - Assert-That $localCatMatch.Success ` - "Test-UnityEditMode から -testCategory の値を読み取れる (読み取れなければ以下は空振りする)" - if ($localCatMatch.Success) { $localCategory = $localCatMatch.Groups['cat'].Value } +if ($exclusionDefMatches.Count -eq 1) { $localCategory = $exclusionDefMatches[0].Groups['cat'].Value } + +# Test-UnityGraphics にも '-testCategory' が在る(値は 'Graphics'、 +# -nographics を渡さない側、正の値なので同じ定義を使わない)ので、 +# 対象の関数だけを名前で切り出してから読む。このファイルのトップレベル +# 関数はすべて列 0 の '}' で閉じる規約(tools/dev.ps1 の他の関数と同じ) +# なので、それを終端として使う。 +# +# **定義を持つだけでは足りない。** 両方のレーンが実際にそれを参照している +# ことを見る —— 変数を定義しただけで呼び出し側が直書きの文字列のままでも、 +# 説明のコメントに変数名を書いておけば下の素朴な部分文字列一致は通って +# しまう(実測: 引数を直書きに戻し、コメントだけ変数名を残す形を試したら +# 最初の版はここを PASS のまま見逃した)。そこで **コード上の引数の形** +# (`'-testCategory', $script:UnityGraphicsExclusionCategory`)そのものを +# 探すよう狭めた。 +# +# **それでもこの assertion 単体は「直書きに戻していない」ことの証明には +# ならない。** コメントが偶然この引数の形そのもの(この関数を直書きに +# 戻したうえで、コメントに `'-testCategory', +# $script:UnityGraphicsExclusionCategory` という文字列を書く)を含んで +# いれば、この assertion は再び PASS する(実測。正規表現はコードと +# コメントを区別しない)。**直書きへの回帰を実際に捕まえるのは、下の +# 「コピーが増えていない」assertion(否定形の -testCategory リテラルを +# 探す)である。この 2 つは対になって初めて 1 つの門になり、どちらか +# 片方だけでは足りない。** +foreach ($fnName in @('Test-UnityEditMode', 'Test-UnityTarball')) { + $fnMatch = [regex]::Match($devPs1Raw, "(?ms)^function $fnName \{.*?^\}") + Assert-That $fnMatch.Success ` + "tools/dev.ps1 から $fnName 関数を切り出せる (切り出せなければ以下は空振りする)" + if ($fnMatch.Success) { + $usagePattern = "'-testCategory',\s*\`$script:UnityGraphicsExclusionCategory\b" + Assert-That ($fnMatch.Value -match $usagePattern) ` + "$fnName's text contains the '-testCategory', `$script:UnityGraphicsExclusionCategory argument shape (this alone does not prove the argument isn't hardcoded elsewhere in a way a comment happens to echo — see the paired literal-copy check below)" + } } +# **コピーが増えていないことも見る。** 定義行そのもの(上の +# $exclusionDefMatches が既に見ている)を除いて、否定形の -testCategory を +# クォートされた文字列リテラルで直書きした箇所が 1 つも無いこと。 +# +# **単独で万能ではない、と正直に書く。** 上の「$fnName が +# $script:UnityGraphicsExclusionCategory を引数として渡している」assertion +# は、コメントがたまたま同じ引数の形(`'-testCategory', +# $script:UnityGraphicsExclusionCategory`)を書いていれば、引数自体を +# 直書きに戻していても PASS してしまう(実測)。実際に直書きへの回帰を +# 捕まえるのはこちらの assertion であり、**2 つは対になって初めて 1 つの +# 門になる** —— どちらか片方だけでは足りない。 +# +# クォート文字は `'` と `"` の両方を見る——シングルクォートだけを見ていた +# 版は `"-testCategory", "!Graphics"`(有効な PowerShell で挙動は同じ)を +# 素通ししていた(実測)。**それでも万能ではない**: 引数を splatting や +# 文字列連結で組み立てた形はどちらも素通りする。ここで捕まえるのは +# 「素朴な直書き」だけで、意図的に検査を迂回する書き方までは狙っていない。 +$literalNegatedCategoryMatches = [regex]::Matches($devPs1Raw, '[''"]-testCategory[''"],\s*[''"]!(?[^''"]+)[''"]') +Assert-That ($literalNegatedCategoryMatches.Count -eq 0) ` + ("tools/dev.ps1 has no literal negated -testCategory value outside " + + "`$script:UnityGraphicsExclusionCategory (saw $($literalNegatedCategoryMatches.Count))") + # ci-unity.yml 側。**単純な「customParameters: の行を探す」では足りない** —— # matrix の 2 つの lane(リテラル文字列)に加えて、customParameters を実際に # action へ渡す with: の 1 行(`${{ matrix.customParameters }}`)も同じ @@ -1066,7 +1116,7 @@ if ($ciCategoryLines.Count -eq 1) { # 「$null -eq $null」のような偶然の一致を PASS と報告する必要は無い。 if ($null -ne $localCategory -and $null -ne $ciCategory) { Assert-That ($localCategory -eq $ciCategory) ` - "ci-unity.yml's EditMode -testCategory ('$ciCategory') matches tools/dev.ps1's Test-UnityEditMode ('$localCategory')" + "ci-unity.yml's EditMode -testCategory ('$ciCategory') matches tools/dev.ps1's `$script:UnityGraphicsExclusionCategory ('$localCategory')" } # **matrix の宣言だけでは足りない。** 上のリテラル判定は