From 0aa9b025e479965a92c46cf154ac6e7264e0cee4 Mon Sep 17 00:00:00 2001 From: Widthdom Date: Sat, 25 Jul 2026 19:29:06 +0900 Subject: [PATCH] Fix public version metadata alignment --- CHANGELOG.md | 4 ++ .../Diagnostics/SystemInfo.cs | 42 +++++++++++- .../CiAutomationConfigurationTests.cs | 44 ++++++++++++ .../Core/Diagnostics/SystemInfoTests.cs | 68 +++++++++++++++---- .../ProgramRunnerTests.HelpVersion.cs | 9 ++- PACKAGE_README.md | 6 +- ProgramRunner.cs | 2 +- README.md | 16 +++-- Runner/ProgramRunner.HelpText.cs | 4 +- USER_GUIDE.md | 22 +++--- doc/DEVELOPER_GUIDE.md | 6 +- doc/TESTING_GUIDE.md | 4 ++ doc/samples/audit_log.json | 2 +- doc/samples/diff_report.html | 2 +- doc/samples/diff_report.md | 2 +- 15 files changed, 192 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f520958..1f8af8d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), #### Fixed +- **Public version and documentation metadata now match the actual build** — `nildiff --version`, logs, and generated reports now use the same three-part SemVer as `version.json`, GitHub releases, and NuGet, while `nildiff --doctor` retains the detailed build/commit version for diagnostics. C# badges now reflect the .NET 8 build's C# 12 language version, source-build instructions use the real repository URL, and committed report samples have current public metadata. Affected: `FolderDiffIL4DotNet.Core/Diagnostics/SystemInfo.cs`, `ProgramRunner.cs`, `Runner/ProgramRunner.HelpText.cs`, `README.md`, `USER_GUIDE.md`, `PACKAGE_README.md`, `doc/DEVELOPER_GUIDE.md`, `doc/TESTING_GUIDE.md`, `doc/samples/*`. Tests: `SystemInfoTests`, `ProgramRunnerTests`, `CiAutomationConfigurationTests`. + - **Git-based tests no longer inherit user signing configuration** — Temporary repositories now use a shared helper that isolates global/system Git configuration, disables commit/tag signing and hooks locally, and forces non-interactive execution without modifying user configuration. Regression coverage verifies that commits and annotated tags succeed even when the isolated global configuration enables signing. Affected: `FolderDiffIL4DotNet.Tests/Helpers/TestGitRepository.cs`, `FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs`, `FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj`, `doc/TESTING_GUIDE.md`. Tests: `TestGitRepositoryTests`, `CiAutomationConfigurationTests`. ### [1.21.0] - 2026-07-22 @@ -1700,6 +1702,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), #### 修正 +- **公開バージョンと文書メタデータを実際のビルドへ統一** — `nildiff --version`、ログ、生成レポートは `version.json`、GitHub リリース、NuGet と同じ 3 要素 SemVer を使い、`nildiff --doctor` では診断用の詳細なビルド/コミットバージョンを維持します。C# バッジを .NET 8 ビルドの C# 12 に合わせ、ソースビルド手順を実際のリポジトリ URL に変更し、コミット済みレポートサンプルの公開メタデータも更新しました。対象: `FolderDiffIL4DotNet.Core/Diagnostics/SystemInfo.cs`, `ProgramRunner.cs`, `Runner/ProgramRunner.HelpText.cs`, `README.md`, `USER_GUIDE.md`, `PACKAGE_README.md`, `doc/DEVELOPER_GUIDE.md`, `doc/TESTING_GUIDE.md`, `doc/samples/*`。テスト: `SystemInfoTests`, `ProgramRunnerTests`, `CiAutomationConfigurationTests`。 + - **Git ベースのテストがユーザーの署名設定を継承しないよう修正** — 一時リポジトリは、グローバル/システム Git 設定を分離し、commit/tag 署名と hook をローカルで無効化して、ユーザー設定を変更せず非対話実行する共通 helper を使うようになりました。分離済みグローバル設定で署名を有効化しても commit と annotated tag が成功することを回帰テストで検証します。対象: `FolderDiffIL4DotNet.Tests/Helpers/TestGitRepository.cs`, `FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs`, `FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj`, `doc/TESTING_GUIDE.md`。テスト: `TestGitRepositoryTests`, `CiAutomationConfigurationTests`。 ### [1.21.0] - 2026-07-22 diff --git a/FolderDiffIL4DotNet.Core/Diagnostics/SystemInfo.cs b/FolderDiffIL4DotNet.Core/Diagnostics/SystemInfo.cs index 1a3fb939..f1ef5017 100644 --- a/FolderDiffIL4DotNet.Core/Diagnostics/SystemInfo.cs +++ b/FolderDiffIL4DotNet.Core/Diagnostics/SystemInfo.cs @@ -47,12 +47,46 @@ public static string GetComputerName() } /// - /// Returns the user-facing version string for the assembly containing the given type. - /// 実行アセンブリの表示用バージョン文字列を取得します。 + /// Returns the public three-part SemVer for the assembly containing the given type. + /// 指定した型を含むアセンブリの公開用 3 要素 SemVer を返します。 /// - /// どのバージョン情報も取得できなかった場合。 + /// is . + /// の場合。 + /// No usable public version is available. + /// 公開用バージョンを取得できない場合。 public static string GetAppVersion(Type programType) { + ArgumentNullException.ThrowIfNull(programType); + + var assembly = programType.Assembly; + var fileVersionAttribute = System.Reflection.CustomAttributeExtensions + .GetCustomAttribute(assembly); + if (Version.TryParse(fileVersionAttribute?.Version, out var fileVersion) && fileVersion.Build >= 0) + { + return $"{fileVersion.Major}.{fileVersion.Minor}.{fileVersion.Build}"; + } + + var fallbackVersion = assembly.GetName().Version; + if (fallbackVersion == null || fallbackVersion.Build < 0) + { + throw new InvalidOperationException(ERROR_VERSION_STRING_EMPTY); + } + + return $"{fallbackVersion.Major}.{fallbackVersion.Minor}.{fallbackVersion.Build}"; + } + + /// + /// Returns the detailed build version for diagnostics, including commit metadata when available. + /// コミットメタデータを利用できる場合はそれを含む、診断用の詳細ビルドバージョンを返します。 + /// + /// is . + /// の場合。 + /// No diagnostic version is available. + /// 診断用バージョンを取得できない場合。 + public static string GetDiagnosticAppVersion(Type programType) + { + ArgumentNullException.ThrowIfNull(programType); + var assembly = programType.Assembly; var infoAttr = System.Reflection.CustomAttributeExtensions .GetCustomAttribute(assembly); @@ -63,8 +97,10 @@ public static string GetAppVersion(Type programType) { throw new InvalidOperationException(ERROR_VERSION_STRING_EMPTY); } + return verToShow; } + private static string? TryGetEnvironmentMachineName() { try diff --git a/FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs b/FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs index 96c7bd55..cbdb8143 100644 --- a/FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs +++ b/FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs @@ -152,6 +152,50 @@ public void PackageJson_MetadataMatchesRepository() Assert.Contains("nildiff", packageJson.GetProperty("description").GetString(), StringComparison.OrdinalIgnoreCase); } + /// + /// Verifies that public version, language, repository, and sample metadata stay aligned. + /// 公開バージョン・言語・リポジトリ・サンプルのメタデータが一致し続けることを検証します。 + /// + [Fact] + [Trait("Category", "Unit")] + public void PublicMetadata_MatchesVersionJsonAndCurrentBuild() + { + using var versionDocument = JsonDocument.Parse(File.ReadAllText(GetRepositoryFilePath("version.json"))); + var publicVersion = versionDocument.RootElement.GetProperty("version").GetString(); + Assert.False(string.IsNullOrWhiteSpace(publicVersion)); + Assert.Equal(3, publicVersion!.Split('.').Length); + + var readme = File.ReadAllText(GetRepositoryFilePath("README.md")); + var userGuide = File.ReadAllText(GetRepositoryFilePath("USER_GUIDE.md")); + var packageReadme = File.ReadAllText(GetRepositoryFilePath("PACKAGE_README.md")); + string[] userDocuments = { readme, userGuide, packageReadme }; + + foreach (var document in userDocuments) + { + Assert.DoesNotContain("", document, StringComparison.Ordinal); + Assert.DoesNotContain("<リポジトリURL>", document, StringComparison.Ordinal); + Assert.Contains("--version", document, StringComparison.Ordinal); + } + + const string cloneCommand = "git clone https://github.com/Widthdom/FolderDiffIL4DotNet.git"; + Assert.Contains(cloneCommand, readme, StringComparison.Ordinal); + Assert.Contains(cloneCommand, userGuide, StringComparison.Ordinal); + Assert.Contains("C%23-12-", readme, StringComparison.Ordinal); + Assert.Contains("C%23-12-", userGuide, StringComparison.Ordinal); + Assert.DoesNotContain("C%23-13-", readme, StringComparison.Ordinal); + Assert.DoesNotContain("C%23-13-", userGuide, StringComparison.Ordinal); + Assert.Contains("C# 12", packageReadme, StringComparison.Ordinal); + + var markdownSample = File.ReadAllText(GetRepositoryFilePath("doc", "samples", "diff_report.md")); + var htmlSample = File.ReadAllText(GetRepositoryFilePath("doc", "samples", "diff_report.html")); + using var auditSample = JsonDocument.Parse( + File.ReadAllText(GetRepositoryFilePath("doc", "samples", "audit_log.json"))); + + Assert.Contains($"nildiff {publicVersion}", markdownSample, StringComparison.Ordinal); + Assert.Contains($"nildiff {publicVersion}", htmlSample, StringComparison.Ordinal); + Assert.Equal(publicVersion, auditSample.RootElement.GetProperty("appVersion").GetString()); + } + /// /// Verifies that CI restores the locked npm dependency graph, runs every Jest test, and blocks high-severity audit findings on a pinned Node.js version. /// CI が固定 Node.js バージョンで npm のロック済み依存グラフを復元し、全 Jest テストを実行して High 以上の監査検出をブロックすることを検証します。 diff --git a/FolderDiffIL4DotNet.Tests/Core/Diagnostics/SystemInfoTests.cs b/FolderDiffIL4DotNet.Tests/Core/Diagnostics/SystemInfoTests.cs index e1e01894..84c08903 100644 --- a/FolderDiffIL4DotNet.Tests/Core/Diagnostics/SystemInfoTests.cs +++ b/FolderDiffIL4DotNet.Tests/Core/Diagnostics/SystemInfoTests.cs @@ -1,4 +1,6 @@ using System; +using System.Reflection; +using System.Reflection.Emit; using FolderDiffIL4DotNet.Core.Diagnostics; using Xunit; @@ -21,22 +23,60 @@ public void GetComputerName_ReturnsNonEmptyString() [Fact] public void GetAppVersion_WithValidType_ReturnsNonEmptyString() { - // Use the Program class type / Program クラス型を使用 + var fileVersionAttribute = typeof(FolderDiffIL4DotNet.Program).Assembly + .GetCustomAttribute(); + Assert.NotNull(fileVersionAttribute); + Assert.True(Version.TryParse(fileVersionAttribute.Version, out var fileVersion)); + var expectedVersion = $"{fileVersion.Major}.{fileVersion.Minor}.{fileVersion.Build}"; + var version = SystemInfo.GetAppVersion(typeof(FolderDiffIL4DotNet.Program)); - Assert.False(string.IsNullOrWhiteSpace(version)); + + Assert.Equal(expectedVersion, version); + Assert.Equal(3, version.Split('.').Length); } [Fact] - public void GetAppVersion_WithValidType_DoesNotContainPlusGitMetadata() + public void GetAppVersion_WithNonZeroPatchVersion_PreservesPatchComponent() { - // If informational version contains '+' git hash suffix, verify it's still returned - // (the method does not strip metadata — this test documents that behavior). - // InformationalVersion に '+' git ハッシュサフィックスが含まれる場合も - // そのまま返されることを文書化するテスト。 - var version = SystemInfo.GetAppVersion(typeof(FolderDiffIL4DotNet.Program)); - // The version should be non-null regardless of metadata presence - // メタデータの有無にかかわらず、バージョンは null であってはならない - Assert.NotNull(version); + var assemblyName = new AssemblyName($"SystemInfoVersionTest_{Guid.NewGuid():N}"); + var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly( + assemblyName, + AssemblyBuilderAccess.Run); + var fileVersionConstructor = typeof(AssemblyFileVersionAttribute) + .GetConstructor(new[] { typeof(string) }); + Assert.NotNull(fileVersionConstructor); + assemblyBuilder.SetCustomAttribute( + new CustomAttributeBuilder(fileVersionConstructor, new object[] { "1.20.6.42" })); + var testType = assemblyBuilder + .DefineDynamicModule(assemblyName.Name!) + .DefineType("VersionedProgram") + .CreateType(); + Assert.NotNull(testType); + + var version = SystemInfo.GetAppVersion(testType); + + Assert.Equal("1.20.6", version); + } + + [Fact] + public void GetDiagnosticAppVersion_WithValidType_PreservesDetailedVersion() + { + var assembly = typeof(FolderDiffIL4DotNet.Program).Assembly; + var informationalVersion = System.Reflection.CustomAttributeExtensions + .GetCustomAttribute(assembly) + ?.InformationalVersion; + + var diagnosticVersion = SystemInfo.GetDiagnosticAppVersion(typeof(FolderDiffIL4DotNet.Program)); + + Assert.False(string.IsNullOrWhiteSpace(diagnosticVersion)); + Assert.StartsWith( + SystemInfo.GetAppVersion(typeof(FolderDiffIL4DotNet.Program)), + diagnosticVersion, + StringComparison.Ordinal); + if (!string.IsNullOrWhiteSpace(informationalVersion)) + { + Assert.Equal(informationalVersion, diagnosticVersion); + } } [Fact] @@ -76,11 +116,13 @@ public void GetComputerName_ConsecutiveCalls_ReturnsSameValue() [Fact] public void GetAppVersion_ConsecutiveCalls_ReturnsSameValue() { - // GetAppVersion should return deterministic results across calls. - // GetAppVersion は呼び出しごとに同じ結果を返すこと。 var version1 = SystemInfo.GetAppVersion(typeof(FolderDiffIL4DotNet.Program)); var version2 = SystemInfo.GetAppVersion(typeof(FolderDiffIL4DotNet.Program)); + var diagnosticVersion1 = SystemInfo.GetDiagnosticAppVersion(typeof(FolderDiffIL4DotNet.Program)); + var diagnosticVersion2 = SystemInfo.GetDiagnosticAppVersion(typeof(FolderDiffIL4DotNet.Program)); + Assert.Equal(version1, version2); + Assert.Equal(diagnosticVersion1, diagnosticVersion2); } } } diff --git a/FolderDiffIL4DotNet.Tests/ProgramRunnerTests.HelpVersion.cs b/FolderDiffIL4DotNet.Tests/ProgramRunnerTests.HelpVersion.cs index d7ed1920..3979daca 100644 --- a/FolderDiffIL4DotNet.Tests/ProgramRunnerTests.HelpVersion.cs +++ b/FolderDiffIL4DotNet.Tests/ProgramRunnerTests.HelpVersion.cs @@ -14,6 +14,7 @@ using FolderDiffIL4DotNet.Services; using FolderDiffIL4DotNet.Tests.Helpers; using Xunit; +using SystemInfo = FolderDiffIL4DotNet.Core.Diagnostics.SystemInfo; namespace FolderDiffIL4DotNet.Tests { @@ -283,6 +284,10 @@ public void WriteDoctorReport_WhenNoDisassemblerAvailable_ReturnsExecutionFailed Assert.Equal(4, exitCode); Assert.Contains("nildiff doctor", stdout.ToString(), StringComparison.Ordinal); + Assert.Contains( + $"Version: {SystemInfo.GetDiagnosticAppVersion(typeof(Program))}", + stdout.ToString(), + StringComparison.Ordinal); Assert.Contains("Unavailable", stdout.ToString(), StringComparison.Ordinal); Assert.Contains("No disassembler tool was detected", stderr.ToString(), StringComparison.Ordinal); } @@ -426,7 +431,9 @@ public async Task RunAsync_VersionFlag_ExitsZeroWithVersionOutput() Assert.Equal(0, exitCode); var output = sw.ToString().Trim(); - Assert.False(string.IsNullOrWhiteSpace(output), "Version output should not be empty."); + Assert.Equal(SystemInfo.GetAppVersion(typeof(Program)), output); + Assert.Equal(3, output.Split('.').Length); + Assert.DoesNotContain("+", output, StringComparison.Ordinal); // Logger should NOT have been initialized // ロガーは初期化されていないはず Assert.Empty(logger.Messages); diff --git a/PACKAGE_README.md b/PACKAGE_README.md index 438472c0..6fa2f7a9 100644 --- a/PACKAGE_README.md +++ b/PACKAGE_README.md @@ -23,7 +23,10 @@ nildiff --wizard # Show help nildiff --help -# Check IL disassembler detection +# Show the public SemVer used by GitHub releases and NuGet +nildiff --version + +# Check the diagnostic build/commit version and IL disassembler detection nildiff --doctor ``` @@ -77,6 +80,7 @@ Run `nildiff --doctor` to verify whether `dotnet-ildasm` or `ilspycmd` is visibl ## Requirements - [.NET SDK 8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) or later +- C# 12 when building from source ## License diff --git a/ProgramRunner.cs b/ProgramRunner.cs index 46dd395a..af4e7a34 100644 --- a/ProgramRunner.cs +++ b/ProgramRunner.cs @@ -467,7 +467,7 @@ internal static int WriteDoctorReport( ArgumentNullException.ThrowIfNull(error); output.WriteLine("nildiff doctor"); - output.WriteLine($"Version: {SystemInfo.GetAppVersion(typeof(Program))}"); + output.WriteLine($"Version: {SystemInfo.GetDiagnosticAppVersion(typeof(Program))}"); output.WriteLine(); output.WriteLine("IL disassembler probes:"); output.WriteLine(" Tool Status Version Path"); diff --git a/README.md b/README.md index 2d29dadf..8bdfaa22 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![Performance Regression Test](https://github.com/Widthdom/FolderDiffIL4DotNet/actions/workflows/benchmark-regression.yml/badge.svg)](https://github.com/Widthdom/FolderDiffIL4DotNet/actions/workflows/benchmark-regression.yml) ![.NET 8](https://img.shields.io/badge/.NET-8.0-512BD4?logo=dotnet&logoColor=white) -![C#](https://img.shields.io/badge/C%23-13-239120?logo=csharp&logoColor=white) +![C#](https://img.shields.io/badge/C%23-12-239120?logo=csharp&logoColor=white) ![Platform](https://img.shields.io/badge/Platform-Windows%20%7C%20macOS%20%7C%20Linux-lightgrey) ![License](https://img.shields.io/badge/License-MIT-blue) @@ -49,10 +49,12 @@ Check IL disassembler detection: nildiff --doctor ``` +`nildiff --version` prints the same public SemVer used by the GitHub release and NuGet package. `nildiff --doctor` retains the detailed build/commit version for diagnostics. + Build from source: ```bash -git clone +git clone https://github.com/Widthdom/FolderDiffIL4DotNet.git cd FolderDiffIL4DotNet dotnet build dotnet run -- "/path/to/old-folder" "/path/to/new-folder" "my-comparison" --no-pause @@ -77,7 +79,8 @@ Common options: | `--print-config` | Print the effective builder state after env-var and supported CLI overrides without semantic validation. | | `--validate-config` | Validate `config.json` plus `FOLDERDIFF_*` environment-variable overrides before runtime CLI overrides are applied. | | `--open-reports` | Open the reports folder and exit. | -| `--doctor` | Probe `dotnet-ildasm` / `ilspycmd` availability and print install guidance. | +| `--version` | Print the public release/NuGet SemVer and exit. | +| `--doctor` | Print build/commit diagnostics, probe `dotnet-ildasm` / `ilspycmd` availability, and show install guidance. | Full CLI behavior, HTML review workflow, integrity checks, semantic-change tables, and configuration details live in [USER_GUIDE.md](USER_GUIDE.md#readme-en-usage). @@ -165,10 +168,12 @@ IL 逆アセンブラ検出を確認する: nildiff --doctor ``` +`nildiff --version` は GitHub リリースおよび NuGet パッケージと同じ公開 SemVer を表示します。`nildiff --doctor` では診断用の詳細なビルド/コミットバージョンを引き続き確認できます。 + ソースからビルドする: ```bash -git clone +git clone https://github.com/Widthdom/FolderDiffIL4DotNet.git cd FolderDiffIL4DotNet dotnet build dotnet run -- "/path/to/old-folder" "/path/to/new-folder" "my-comparison" --no-pause @@ -193,7 +198,8 @@ nildiff [report-label] [options] | `--print-config` | 環境変数と対応 CLI オーバーライドを適用した builder 状態を、セマンティック検証なしでそのまま出力するため、範囲外を含む effective config の診断にも使えます。 | | `--validate-config` | [`config.json`](config.json) に `FOLDERDIFF_*` 環境変数オーバーライドを適用した状態を、実行時 CLI オーバーライド適用前に検証します。 | | `--open-reports` | レポートフォルダを開いて終了します。 | -| `--doctor` | `dotnet-ildasm` / `ilspycmd` の利用可否を確認し、インストール案内を出します。 | +| `--version` | 公開リリース/NuGet と同じ SemVer を表示して終了します。 | +| `--doctor` | ビルド/コミット診断を表示し、`dotnet-ildasm` / `ilspycmd` の利用可否確認とインストール案内を行います。 | CLI の詳細、HTML レビュー手順、整合性検証、セマンティック変更テーブル、設定詳細は [USER_GUIDE.md](USER_GUIDE.md#readme-ja-usage) を参照してください。 diff --git a/Runner/ProgramRunner.HelpText.cs b/Runner/ProgramRunner.HelpText.cs index c1141741..a1ea402d 100644 --- a/Runner/ProgramRunner.HelpText.cs +++ b/Runner/ProgramRunner.HelpText.cs @@ -16,10 +16,10 @@ public sealed partial class ProgramRunner " When omitted, a high-resolution timestamp label is auto-generated.\n\n" + "Options:\n" + " --help, -h Show this help message and exit.\n" + - " --version Show the application version and exit.\n" + + " --version Show the public SemVer version and exit.\n" + " --banner Show the ASCII-art banner and exit.\n" + " --no-banner Suppress the startup banner during normal diff runs.\n" + - " --doctor Probe IL disassembler availability and print install guidance.\n" + + " --doctor Print build/commit diagnostics and probe IL disassembler availability.\n" + " --print-config Diagnostic: print env+supported CLI overrides as indented JSON without semantic validation.\n" + " --validate-config Validate config.json + env overrides before runtime CLI overrides (0=valid, 3=invalid).\n" + " --no-pause Skip key-wait at process end.\n" + diff --git a/USER_GUIDE.md b/USER_GUIDE.md index bed03e72..371835cf 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -8,7 +8,7 @@ [![Performance Regression Test](https://github.com/Widthdom/FolderDiffIL4DotNet/actions/workflows/benchmark-regression.yml/badge.svg)](https://github.com/Widthdom/FolderDiffIL4DotNet/actions/workflows/benchmark-regression.yml) ![.NET 8](https://img.shields.io/badge/.NET-8.0-512BD4?logo=dotnet&logoColor=white) -![C#](https://img.shields.io/badge/C%23-13-239120?logo=csharp&logoColor=white) +![C#](https://img.shields.io/badge/C%23-12-239120?logo=csharp&logoColor=white) ![Platform](https://img.shields.io/badge/Platform-Windows%20%7C%20macOS%20%7C%20Linux-lightgrey) ![License](https://img.shields.io/badge/License-MIT-blue) @@ -34,7 +34,8 @@ nildiff "/path/to/old-folder" "/path/to/new-folder" "my-comparison" --no-pause ``` If you want to inspect the current configuration or open the reports folder, use `nildiff --print-config` or `nildiff --open-reports`. -If IL comparison falls back to SHA256, run `nildiff --doctor` to check `dotnet-ildasm` / `ilspycmd` detection. +`nildiff --version` prints the same public SemVer used by the GitHub release and NuGet package. +If IL comparison falls back to SHA256, run `nildiff --doctor` to inspect the detailed build/commit version and check `dotnet-ildasm` / `ilspycmd` detection. Generated artifacts are written under `Reports/