From f5644a729c5a48f7841091ab241cec70a935836f Mon Sep 17 00:00:00 2001 From: HAKAMIQ <167469500+HAKAMIQ@users.noreply.github.com> Date: Sun, 2 Aug 2026 14:11:01 +0300 Subject: [PATCH] fix(release): repair and enforce published executable smoke gate --- .github/workflows/ci.yml | 24 +- .github/workflows/release.yml | 8 +- .gitignore | 4 +- CHANGES.md | 56 +- CONTRIBUTING.md | 10 +- CsoKit.slnx | 8 + Directory.Build.props | 8 + Hakamiq.CsoKit.slnx | 6 - LICENSE.txt | 4 +- README.md | 46 +- RELEASE_NOTES.md | 4 +- SOURCE-MANIFEST.sha256 | 260 +++ SOURCE_FILES.txt | 259 +++ THIRD_PARTY_NOTICES.md | 8 +- VERSION | 1 + docs/CLI.md | 78 +- docs/HARDENING_IMPLEMENTATION_REPORT.md | 145 ++ docs/NATIVE_BUILD.md | 30 +- docs/SECURITY_HARDENING.md | 57 + docs/archive/CHANGELOG_FIX_NOTES.md | 24 +- docs/archive/R1_ARCHITECTURE_REPAIR.md | 2 +- docs/archive/R3C_RELEASE_HARDENING.md | 6 +- docs/archive/R3D_BENCHMARK_TRUTH.md | 4 +- docs/archive/R3E_REAL_CORPUS_EVIDENCE.md | 4 +- docs/archive/RELEASE_0_5_0_SCORECARD.md | 2 +- docs/archive/RELEASE_SCORECARD.md | 6 +- docs/release/RELEASE_0_6_0_GATE.md | 2 +- .../CMakeLists.txt | 54 +- native/CsoKit.Native/include/csokit_native.h | 95 + .../CsoKit.Native/include/csokit_version.h.in | 6 + .../src/csokit_native.cpp} | 99 +- .../include/hakamiq_cso_native.h | 95 - scripts/Build-Native.ps1 | 12 +- scripts/OutputFileNamePolicy.ps1 | 32 + scripts/Publish-Release.ps1 | 306 ++-- scripts/Publish-SourcePackage.ps1 | 55 +- scripts/Run-BenchmarkTruthLayer.ps1 | 22 +- scripts/Run-FinalReleaseGate.ps1 | 25 +- scripts/Run-OfficialReleaseGate.ps1 | 37 +- scripts/Run-ProfileRoundtripMatrix.ps1 | 68 +- scripts/Run-PublishedExeSmoke.ps1 | 57 +- scripts/Run-RealLocalCorpusGate.ps1 | 10 +- scripts/Run-ReleaseGate.ps1 | 20 +- scripts/Run-RoundtripGate.ps1 | 58 +- scripts/Verify-Hardening.ps1 | 193 ++ scripts/Verify-Release.ps1 | 25 +- src/{Hakamiq.Cso.App => CsoKit.App}/App.xaml | 2 +- src/CsoKit.App/App.xaml.cs | 7 + .../Assets/Icons/advanced_key.png | Bin .../Assets/Icons/csokit.ico} | Bin .../Assets/Icons/csokit_32.png} | Bin .../Assets/Icons/status_error.png | Bin .../Assets/Icons/status_success.png | Bin .../CsoKit.App.csproj} | 23 +- .../Localization/ArabicUiText.cs | 22 +- .../MainWindow.xaml | 9 +- .../MainWindow.xaml.cs | 12 +- .../Models/UiLogEntry.cs | 2 +- .../Models/UiOperationKind.cs | 2 +- .../Models/UiTaskItem.cs | 2 +- src/CsoKit.App/Properties/AssemblyInfo.cs | 3 + .../Services/OperationReportService.cs | 511 ++++++ .../MainWindowViewModel.Operations.cs | 402 +++++ .../ViewModels/MainWindowViewModel.cs | 709 ++++++++ .../ViewModels/OperationSummaryViewModel.cs | 4 +- .../CsoKit.Application.csproj | 12 + src/CsoKit.Application/CsoOperationData.cs | 106 ++ src/CsoKit.Application/CsoOperationDetail.cs | 30 + .../CsoOperationDetailsBuilder.cs | 63 + src/CsoKit.Application/CsoOperationResult.cs | 69 + .../CsoOperationService.Verification.cs | 738 ++++++++ src/CsoKit.Application/CsoOperationService.cs | 845 +++++++++ .../CliExitCodes.cs | 2 +- .../Commands/AnalyzeCommand.cs | 6 +- .../Commands/CodecsCommand.cs | 4 +- .../Commands/CompressCommand.cs | 159 +- .../Commands/CsoCommandDispatcher.cs | 42 +- .../Commands/CsoCommandError.cs | 2 +- .../Commands/CsoCompressJsonContract.cs | 147 +- .../Commands/CsoProfileOutput.cs | 4 +- .../Commands/DecompressCommand.cs | 99 +- .../Commands/DetectCommand.cs | 6 +- .../Commands/InfoCommand.cs | 6 +- .../Commands/JsonConsole.cs | 2 +- .../Commands/NativeInfoCommand.cs | 4 +- .../Commands/RepairCommand.cs | 187 +- src/CsoKit.Cli/Commands/VerifyCommand.cs | 313 ++++ .../CsoKit.Cli.csproj} | 12 +- .../Program.cs | 2 +- .../Analysis/PspIsoAnalysisResult.cs | 4 +- .../Compression/CsoWorkerPolicy.cs | 58 + .../Trials/CodecTrialCandidateResult.cs | 2 +- .../Trials/CodecTrialDecisionMetrics.cs | 2 +- .../Compression/Trials/CodecTrialReport.cs | 2 +- .../Compression/Trials/CodecTrialSummary.cs | 2 +- .../Trials/CodecTrialSummaryBuilder.cs | 2 +- .../CsoKit.Core.csproj} | 10 +- .../Containers/BlockContainerReadException.cs | 2 +- .../Containers/BlockContainerReaderFactory.cs | 26 + .../Containers/ContainerDeepVerifier.cs | 13 +- .../Formats/Containers/Cso1ContainerReader.cs | 6 +- .../Formats/Containers/Cso2ContainerReader.cs | 6 +- .../Containers/CsoLikeContainerReader.cs | 6 +- .../Formats/Containers/CsoLikeHeaderReader.cs | 4 +- .../Formats/Containers/DaxContainerReader.cs | 4 +- .../Containers/IBlockContainerReader.cs | 4 +- .../Formats/Containers/IsoContainerReader.cs | 6 +- .../Formats/Containers/Lz4BlockDecoder.cs | 2 +- .../Formats/Containers/ZsoContainerReader.cs | 6 +- .../Formats/Cso/Codecs/CsoCodecKind.cs | 2 +- .../Formats/Cso/Codecs/CsoCodecTrial.cs | 2 +- .../Formats/Cso/Codecs/CsoCodecTrialResult.cs | 2 +- .../Formats/Cso/Codecs/CsoTrialEngine.cs | 4 +- .../Formats/Cso/Codecs/CsoTrialPlan.cs | 2 +- .../Formats/Cso/Codecs/CsoTrialPlanner.cs | 8 +- .../Formats/Cso/Codecs/ICsoCodecTrial.cs | 2 +- .../Cso/Codecs/Managed/ManagedDeflateTrial.cs | 2 +- .../Codecs/Native/NativeLibDeflateTrial.cs | 4 +- .../Codecs/Native/NativeUnavailableTrial.cs | 2 +- .../Cso/Codecs/Native/NativeZlibTrial.cs | 4 +- .../Cso/Codecs/Native/NativeZopfliTrial.cs | 4 +- .../Formats/Cso/CompressionMethod.cs | 2 +- .../Formats/Cso/Cso1Writer.cs | 10 +- .../Formats/Cso/CsoBestCandidateSelector.cs | 2 +- .../Formats/Cso/CsoBlockReader.cs | 2 +- .../Formats/Cso/CsoCompressOptions.cs | 2 +- .../Formats/Cso/CsoCompressProgress.cs | 2 +- .../Formats/Cso/CsoCompressResult.cs | 4 +- .../Formats/Cso/CsoCompressionProfile.cs | 2 +- .../Cso/CsoCompressionProfilePolicy.cs | 2 +- .../Cso/CsoCompressionProfileSettings.cs | 2 +- .../Formats/Cso/CsoCompressionWorker.cs | 4 +- .../Formats/Cso/CsoCompressor.cs | 20 +- .../Formats/Cso/CsoConstants.cs | 2 +- .../Formats/Cso/CsoDecompressOptions.cs | 2 +- .../Formats/Cso/CsoDecompressProgress.cs | 2 +- .../Formats/Cso/CsoDecompressResult.cs | 2 +- .../Formats/Cso/CsoDecompressor.cs | 2 +- .../Formats/Cso/CsoDeepVerifier.cs | 19 +- .../Formats/Cso/CsoDeepVerifyIssue.cs | 2 +- .../Formats/Cso/CsoDeepVerifyResult.cs | 2 +- .../Formats/Cso/CsoDiskSpacePreflight.cs | 2 +- .../Cso/CsoDiskSpacePreflightResult.cs | 2 +- .../Formats/Cso/CsoFileNamePolicy.cs | 184 ++ .../Formats/Cso/CsoHeader.cs | 2 +- .../Formats/Cso/CsoHeaderReadResult.cs | 2 +- .../Formats/Cso/CsoHeaderReader.cs | 2 +- .../Formats/Cso/CsoIndexBuilder.cs | 2 +- .../Formats/Cso/CsoIndexEntry.cs | 2 +- .../Formats/Cso/CsoIndexReadResult.cs | 2 +- .../Formats/Cso/CsoIndexReader.cs | 2 +- .../Formats/Cso/CsoIndexShiftPolicy.cs | 2 +- .../Formats/Cso/CsoMeasureEstimator.cs | 4 +- .../Formats/Cso/CsoMeasureOptions.cs | 2 +- .../Formats/Cso/CsoMeasureResult.cs | 2 +- .../Formats/Cso/CsoOrderedOutputWriter.cs | 2 +- .../Formats/Cso/CsoOutputPathPolicy.cs | 39 +- .../Formats/Cso/CsoOutputSafetyPolicy.cs | 14 +- .../Formats/Cso/CsoOutputSafetyResult.cs | 2 +- .../Formats/Cso/CsoRepairMode.cs | 2 +- .../Formats/Cso/CsoRepairOptions.cs | 2 +- .../Formats/Cso/CsoRepairResult.cs | 4 +- .../Formats/Cso/CsoRepairer.cs | 38 +- .../Formats/Cso/CsoVerificationIssue.cs | 2 +- .../Formats/Cso/CsoVerificationResult.cs | 2 +- .../Formats/Cso/CsoVerifier.cs | 2 +- .../Formats/Cso/RawDeflateVerifier.cs | 2 +- .../Formats/Cso/SectorJob.cs | 2 +- .../Formats/Cso/SectorResult.cs | 4 +- .../Formats/DiscImage/DetectedDiscFormat.cs | 2 +- .../DiscImage/FormatDetectionResult.cs | 2 +- .../Formats/DiscImage/FormatDetector.cs | 4 +- .../Formats/Iso/Iso9660Entry.cs | 2 +- .../Formats/Iso/Iso9660Reader.cs | 2 +- .../Formats/Iso/IsoAlignmentPolicy.cs | 2 +- .../Formats/Iso/IsoAlignmentResult.cs | 2 +- .../Formats/Iso/PspIsoValidationIssue.cs | 2 +- .../Formats/Iso/PspIsoValidationResult.cs | 2 +- .../Formats/Iso/PspIsoValidator.cs | 4 +- .../Formats/Psp/PspDiscIdentity.cs | 2 +- .../Formats/Psp/PspParamSfoReader.cs | 2 +- .../Native/NativeCsoBackend.cs | 2 +- .../Native/NativeCsoCapabilities.cs | 2 +- .../Native/NativeCsoRawCodec.cs | 2 +- .../Native/NativeCsoRuntime.cs | 430 ++--- .../Native/NativeCsoRuntimeInfo.cs | 2 +- src/CsoKit.Core/Properties/AssemblyInfo.cs | 3 + .../Repair/RepairMode.cs | 2 +- .../Repair/RepairPlan.cs | 4 +- .../Repair/StreamingRepairService.cs | 25 +- src/Hakamiq.Cso.App/App.xaml.cs | 7 - .../Services/CsoUiOperationResult.cs | 17 - .../Services/CsoUiOperationService.cs | 1084 ------------ .../ViewModels/MainWindowViewModel.cs | 1549 ----------------- src/Hakamiq.Cso.Cli/Commands/VerifyCommand.cs | 481 ----- .../CsoKit.App.Tests/CsoKit.App.Tests.csproj | 21 + .../OperationReportServiceTests.cs | 46 + .../CsoOperationFileNamePolicyTests.cs | 31 + .../Application/CsoOperationResultTests.cs | 61 + .../Compression/CsoWorkerPolicyTests.cs | 47 + .../CsoKit.Tests.csproj} | 5 +- .../DisableTestParallelization.cs | 0 .../Fixtures/ContainerFixtures.cs | 13 +- .../Formats/CorruptContainerRefusalTests.cs | 6 +- .../Formats/Cso/ContainerDeepVerifierTests.cs | 8 +- .../Formats/Cso/CsoCliContractTests.cs | 163 +- .../Cso/CsoCompressJsonContractTests.cs | 38 +- .../Cso/CsoCompressionDecisionTests.cs | 4 +- .../Cso/CsoCompressionProfilePolicyTests.cs | 4 +- .../Formats/Cso/CsoCompressorTests.cs | 41 +- .../Cso/CsoDecompressorCancellationTests.cs | 4 +- .../Formats/Cso/CsoDecompressorTests.cs | 9 +- .../Formats/Cso/CsoDeepVerifierTests.cs | 4 +- .../Formats/Cso/CsoDiskSpacePreflightTests.cs | 8 +- .../Formats/Cso/CsoFileNamePolicyTests.cs | 47 + .../Formats/Cso/CsoHeaderReaderTests.cs | 4 +- .../Formats/Cso/CsoIndexReaderTests.cs | 4 +- .../Formats/Cso/CsoIndexShiftPolicyTests.cs | 4 +- .../Formats/Cso/CsoMeasureEstimatorTests.cs | 7 +- .../Formats/Cso/CsoOutputPathPolicyTests.cs | 61 +- .../Formats/Cso/CsoOutputSafetyPolicyTests.cs | 57 +- .../Formats/Cso/CsoRepairerTests.cs | 9 +- .../Cso/CsoSectorEngineFoundationTests.cs | 4 +- .../Formats/Cso/CsoTestFileFactory.cs | 14 +- .../Formats/Cso/CsoTrialEngineTests.cs | 6 +- .../Formats/Cso/CsoTrialPlannerTests.cs | 6 +- .../Formats/Cso/CsoVerifierTests.cs | 6 +- .../Cso/DeepVerificationCancellationTests.cs | 55 + .../Formats/DiscImage/FormatDetectorTests.cs | 8 +- .../Formats/GoldenContainerTests.cs | 10 +- .../Formats/Iso/IsoAlignmentPolicyTests.cs | 4 +- .../Formats/Iso/PspIsoValidatorTests.cs | 6 +- .../Formats/PspIsoFixtureTests.cs | 8 +- .../Formats/RepairGoldenFixtureTests.cs | 6 +- .../Native/NativeCsoRuntimeTests.cs | 121 ++ .../Native/NativeLibrarySearchPolicyTests.cs | 42 + .../Native/NativeCsoRuntimeTests.cs | 59 - 237 files changed, 7558 insertions(+), 4667 deletions(-) create mode 100644 CsoKit.slnx create mode 100644 Directory.Build.props delete mode 100644 Hakamiq.CsoKit.slnx create mode 100644 SOURCE-MANIFEST.sha256 create mode 100644 SOURCE_FILES.txt create mode 100644 VERSION create mode 100644 docs/HARDENING_IMPLEMENTATION_REPORT.md create mode 100644 docs/SECURITY_HARDENING.md rename native/{Hakamiq.Cso.Native => CsoKit.Native}/CMakeLists.txt (63%) create mode 100644 native/CsoKit.Native/include/csokit_native.h create mode 100644 native/CsoKit.Native/include/csokit_version.h.in rename native/{Hakamiq.Cso.Native/src/hakamiq_cso_native.cpp => CsoKit.Native/src/csokit_native.cpp} (73%) delete mode 100644 native/Hakamiq.Cso.Native/include/hakamiq_cso_native.h create mode 100644 scripts/OutputFileNamePolicy.ps1 create mode 100644 scripts/Verify-Hardening.ps1 rename src/{Hakamiq.Cso.App => CsoKit.App}/App.xaml (85%) create mode 100644 src/CsoKit.App/App.xaml.cs rename src/{Hakamiq.Cso.App => CsoKit.App}/Assets/Icons/advanced_key.png (100%) rename src/{Hakamiq.Cso.App/Assets/Icons/hakamiq.ico => CsoKit.App/Assets/Icons/csokit.ico} (100%) rename src/{Hakamiq.Cso.App/Assets/Icons/hakamiq_32.png => CsoKit.App/Assets/Icons/csokit_32.png} (100%) rename src/{Hakamiq.Cso.App => CsoKit.App}/Assets/Icons/status_error.png (100%) rename src/{Hakamiq.Cso.App => CsoKit.App}/Assets/Icons/status_success.png (100%) rename src/{Hakamiq.Cso.App/Hakamiq.Cso.App.csproj => CsoKit.App/CsoKit.App.csproj} (57%) rename src/{Hakamiq.Cso.App => CsoKit.App}/Localization/ArabicUiText.cs (95%) rename src/{Hakamiq.Cso.App => CsoKit.App}/MainWindow.xaml (99%) rename src/{Hakamiq.Cso.App => CsoKit.App}/MainWindow.xaml.cs (95%) rename src/{Hakamiq.Cso.App => CsoKit.App}/Models/UiLogEntry.cs (89%) rename src/{Hakamiq.Cso.App => CsoKit.App}/Models/UiOperationKind.cs (78%) rename src/{Hakamiq.Cso.App => CsoKit.App}/Models/UiTaskItem.cs (98%) create mode 100644 src/CsoKit.App/Properties/AssemblyInfo.cs create mode 100644 src/CsoKit.App/Services/OperationReportService.cs create mode 100644 src/CsoKit.App/ViewModels/MainWindowViewModel.Operations.cs create mode 100644 src/CsoKit.App/ViewModels/MainWindowViewModel.cs rename src/{Hakamiq.Cso.App => CsoKit.App}/ViewModels/OperationSummaryViewModel.cs (90%) create mode 100644 src/CsoKit.Application/CsoKit.Application.csproj create mode 100644 src/CsoKit.Application/CsoOperationData.cs create mode 100644 src/CsoKit.Application/CsoOperationDetail.cs create mode 100644 src/CsoKit.Application/CsoOperationDetailsBuilder.cs create mode 100644 src/CsoKit.Application/CsoOperationResult.cs create mode 100644 src/CsoKit.Application/CsoOperationService.Verification.cs create mode 100644 src/CsoKit.Application/CsoOperationService.cs rename src/{Hakamiq.Cso.Cli => CsoKit.Cli}/CliExitCodes.cs (95%) rename src/{Hakamiq.Cso.Cli => CsoKit.Cli}/Commands/AnalyzeCommand.cs (96%) rename src/{Hakamiq.Cso.Cli => CsoKit.Cli}/Commands/CodecsCommand.cs (94%) rename src/{Hakamiq.Cso.Cli => CsoKit.Cli}/Commands/CompressCommand.cs (81%) rename src/{Hakamiq.Cso.Cli => CsoKit.Cli}/Commands/CsoCommandDispatcher.cs (63%) rename src/{Hakamiq.Cso.Cli => CsoKit.Cli}/Commands/CsoCommandError.cs (68%) rename src/{Hakamiq.Cso.Cli => CsoKit.Cli}/Commands/CsoCompressJsonContract.cs (56%) rename src/{Hakamiq.Cso.Cli => CsoKit.Cli}/Commands/CsoProfileOutput.cs (83%) rename src/{Hakamiq.Cso.Cli => CsoKit.Cli}/Commands/DecompressCommand.cs (69%) rename src/{Hakamiq.Cso.Cli => CsoKit.Cli}/Commands/DetectCommand.cs (96%) rename src/{Hakamiq.Cso.Cli => CsoKit.Cli}/Commands/InfoCommand.cs (97%) rename src/{Hakamiq.Cso.Cli => CsoKit.Cli}/Commands/JsonConsole.cs (92%) rename src/{Hakamiq.Cso.Cli => CsoKit.Cli}/Commands/NativeInfoCommand.cs (96%) rename src/{Hakamiq.Cso.Cli => CsoKit.Cli}/Commands/RepairCommand.cs (67%) create mode 100644 src/CsoKit.Cli/Commands/VerifyCommand.cs rename src/{Hakamiq.Cso.Cli/Hakamiq.Cso.Cli.csproj => CsoKit.Cli/CsoKit.Cli.csproj} (53%) rename src/{Hakamiq.Cso.Cli => CsoKit.Cli}/Program.cs (54%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Analysis/PspIsoAnalysisResult.cs (85%) create mode 100644 src/CsoKit.Core/Compression/CsoWorkerPolicy.cs rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Compression/Trials/CodecTrialCandidateResult.cs (87%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Compression/Trials/CodecTrialDecisionMetrics.cs (84%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Compression/Trials/CodecTrialReport.cs (80%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Compression/Trials/CodecTrialSummary.cs (85%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Compression/Trials/CodecTrialSummaryBuilder.cs (98%) rename src/{Hakamiq.Cso.Core/Hakamiq.Cso.Core.csproj => CsoKit.Core/CsoKit.Core.csproj} (50%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Containers/BlockContainerReadException.cs (94%) create mode 100644 src/CsoKit.Core/Formats/Containers/BlockContainerReaderFactory.cs rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Containers/ContainerDeepVerifier.cs (95%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Containers/Cso1ContainerReader.cs (85%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Containers/Cso2ContainerReader.cs (91%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Containers/CsoLikeContainerReader.cs (97%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Containers/CsoLikeHeaderReader.cs (98%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Containers/DaxContainerReader.cs (99%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Containers/IBlockContainerReader.cs (73%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Containers/IsoContainerReader.cs (94%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Containers/Lz4BlockDecoder.cs (98%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Containers/ZsoContainerReader.cs (89%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/Codecs/CsoCodecKind.cs (91%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/Codecs/CsoCodecTrial.cs (75%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/Codecs/CsoCodecTrialResult.cs (91%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/Codecs/CsoTrialEngine.cs (99%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/Codecs/CsoTrialPlan.cs (77%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/Codecs/CsoTrialPlanner.cs (97%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/Codecs/ICsoCodecTrial.cs (81%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/Codecs/Managed/ManagedDeflateTrial.cs (97%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/Codecs/Native/NativeLibDeflateTrial.cs (95%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/Codecs/Native/NativeUnavailableTrial.cs (93%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/Codecs/Native/NativeZlibTrial.cs (95%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/Codecs/Native/NativeZopfliTrial.cs (95%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CompressionMethod.cs (69%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/Cso1Writer.cs (98%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoBestCandidateSelector.cs (99%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoBlockReader.cs (90%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoCompressOptions.cs (93%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoCompressProgress.cs (90%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoCompressResult.cs (95%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoCompressionProfile.cs (76%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoCompressionProfilePolicy.cs (99%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoCompressionProfileSettings.cs (85%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoCompressionWorker.cs (96%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoCompressor.cs (97%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoConstants.cs (90%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoDecompressOptions.cs (84%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoDecompressProgress.cs (91%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoDecompressResult.cs (92%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoDecompressor.cs (99%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoDeepVerifier.cs (97%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoDeepVerifyIssue.cs (85%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoDeepVerifyResult.cs (98%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoDiskSpacePreflight.cs (98%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoDiskSpacePreflightResult.cs (95%) create mode 100644 src/CsoKit.Core/Formats/Cso/CsoFileNamePolicy.cs rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoHeader.cs (95%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoHeaderReadResult.cs (91%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoHeaderReader.cs (99%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoIndexBuilder.cs (96%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoIndexEntry.cs (92%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoIndexReadResult.cs (94%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoIndexReader.cs (99%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoIndexShiftPolicy.cs (97%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoMeasureEstimator.cs (98%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoMeasureOptions.cs (88%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoMeasureResult.cs (98%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoOrderedOutputWriter.cs (96%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoOutputPathPolicy.cs (52%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoOutputSafetyPolicy.cs (80%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoOutputSafetyResult.cs (92%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoRepairMode.cs (68%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoRepairOptions.cs (91%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoRepairResult.cs (98%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoRepairer.cs (95%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoVerificationIssue.cs (85%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoVerificationResult.cs (95%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/CsoVerifier.cs (99%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/RawDeflateVerifier.cs (97%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/SectorJob.cs (84%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Cso/SectorResult.cs (87%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/DiscImage/DetectedDiscFormat.cs (72%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/DiscImage/FormatDetectionResult.cs (93%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/DiscImage/FormatDetector.cs (98%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Iso/Iso9660Entry.cs (72%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Iso/Iso9660Reader.cs (99%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Iso/IsoAlignmentPolicy.cs (95%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Iso/IsoAlignmentResult.cs (91%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Iso/PspIsoValidationIssue.cs (72%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Iso/PspIsoValidationResult.cs (97%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Iso/PspIsoValidator.cs (99%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Psp/PspDiscIdentity.cs (84%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Formats/Psp/PspParamSfoReader.cs (99%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Native/NativeCsoBackend.cs (65%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Native/NativeCsoCapabilities.cs (92%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Native/NativeCsoRawCodec.cs (84%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Native/NativeCsoRuntime.cs (50%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Native/NativeCsoRuntimeInfo.cs (80%) create mode 100644 src/CsoKit.Core/Properties/AssemblyInfo.cs rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Repair/RepairMode.cs (64%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Repair/RepairPlan.cs (66%) rename src/{Hakamiq.Cso.Core => CsoKit.Core}/Repair/StreamingRepairService.cs (79%) delete mode 100644 src/Hakamiq.Cso.App/App.xaml.cs delete mode 100644 src/Hakamiq.Cso.App/Services/CsoUiOperationResult.cs delete mode 100644 src/Hakamiq.Cso.App/Services/CsoUiOperationService.cs delete mode 100644 src/Hakamiq.Cso.App/ViewModels/MainWindowViewModel.cs delete mode 100644 src/Hakamiq.Cso.Cli/Commands/VerifyCommand.cs create mode 100644 tests/CsoKit.App.Tests/CsoKit.App.Tests.csproj create mode 100644 tests/CsoKit.App.Tests/OperationReportServiceTests.cs create mode 100644 tests/CsoKit.Tests/Application/CsoOperationFileNamePolicyTests.cs create mode 100644 tests/CsoKit.Tests/Application/CsoOperationResultTests.cs create mode 100644 tests/CsoKit.Tests/Compression/CsoWorkerPolicyTests.cs rename tests/{Hakamiq.Cso.Tests/Hakamiq.Cso.Tests.csproj => CsoKit.Tests/CsoKit.Tests.csproj} (72%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/DisableTestParallelization.cs (100%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Fixtures/ContainerFixtures.cs (96%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/CorruptContainerRefusalTests.cs (96%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/ContainerDeepVerifierTests.cs (96%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoCliContractTests.cs (64%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoCompressJsonContractTests.cs (77%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoCompressionDecisionTests.cs (99%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoCompressionProfilePolicyTests.cs (97%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoCompressorTests.cs (90%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoDecompressorCancellationTests.cs (90%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoDecompressorTests.cs (95%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoDeepVerifierTests.cs (96%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoDiskSpacePreflightTests.cs (72%) create mode 100644 tests/CsoKit.Tests/Formats/Cso/CsoFileNamePolicyTests.cs rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoHeaderReaderTests.cs (98%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoIndexReaderTests.cs (98%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoIndexShiftPolicyTests.cs (92%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoMeasureEstimatorTests.cs (93%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoOutputPathPolicyTests.cs (61%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoOutputSafetyPolicyTests.cs (60%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoRepairerTests.cs (96%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoSectorEngineFoundationTests.cs (96%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoTestFileFactory.cs (95%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoTrialEngineTests.cs (95%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoTrialPlannerTests.cs (88%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Cso/CsoVerifierTests.cs (96%) create mode 100644 tests/CsoKit.Tests/Formats/Cso/DeepVerificationCancellationTests.cs rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/DiscImage/FormatDetectorTests.cs (91%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/GoldenContainerTests.cs (95%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Iso/IsoAlignmentPolicyTests.cs (92%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/Iso/PspIsoValidatorTests.cs (97%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/PspIsoFixtureTests.cs (93%) rename tests/{Hakamiq.Cso.Tests => CsoKit.Tests}/Formats/RepairGoldenFixtureTests.cs (94%) create mode 100644 tests/CsoKit.Tests/Native/NativeCsoRuntimeTests.cs create mode 100644 tests/CsoKit.Tests/Native/NativeLibrarySearchPolicyTests.cs delete mode 100644 tests/Hakamiq.Cso.Tests/Native/NativeCsoRuntimeTests.cs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 95da995..abc2e47 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,16 +50,26 @@ jobs: } - name: Restore - run: dotnet restore .\Hakamiq.CsoKit.slnx -r win-x64 -p:NuGetAudit=false + run: dotnet restore .\CsoKit.slnx -r win-x64 -p:NuGetAudit=false + + - name: Build native backend + run: .\scripts\Build-Native.ps1 -Configuration Release -Platform x64 - name: Build Debug - run: dotnet build .\Hakamiq.CsoKit.slnx -c Debug --no-restore -p:NuGetAudit=false + run: dotnet build .\CsoKit.slnx -c Debug --no-restore -p:NuGetAudit=false - - name: Test Debug - run: dotnet test .\Hakamiq.CsoKit.slnx -c Debug --no-build + - name: Stage native backend for tests + run: | + $source = ".\artifacts\native-build\win-x64\Release\CsoKit.Native.dll" + $destination = ".\tests\CsoKit.Tests\bin\Debug\net10.0\CsoKit.Native.dll" + if (-not (Test-Path -LiteralPath $source -PathType Leaf)) { + throw "Native test DLL was not found: $source" + } + New-Item -ItemType Directory -Force (Split-Path -Parent $destination) | Out-Null + Copy-Item -LiteralPath $source -Destination $destination -Force - - name: Build native backend - run: .\scripts\Build-Native.ps1 -Configuration Release -Platform x64 + - name: Test Debug with native integration + run: dotnet test .\CsoKit.slnx -c Debug --no-build - name: Publish release package run: .\scripts\Publish-Release.ps1 -Runtime win-x64 @@ -70,6 +80,6 @@ jobs: - name: Upload release ZIP artifact uses: actions/upload-artifact@v7 with: - name: hakamiq-csokit-win-x64 + name: csokit-win-x64 path: artifacts/release/*.zip if-no-files-found: error \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cf90a52..d42b1b8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -82,7 +82,7 @@ jobs: - name: Attest release ZIP uses: actions/attest@v4 with: - subject-path: artifacts/release/hakamiq-csokit-${{ env.RELEASE_VERSION }}-win-x64.zip + subject-path: artifacts/release/csokit-${{ env.RELEASE_VERSION }}-win-x64.zip - name: Attest SHA256 manifest uses: actions/attest@v4 @@ -92,7 +92,7 @@ jobs: - name: Upload workflow artifact uses: actions/upload-artifact@v7 with: - name: hakamiq-csokit-${{ env.RELEASE_VERSION }}-win-x64 + name: csokit-${{ env.RELEASE_VERSION }}-win-x64 path: | artifacts/release/*.zip artifacts/publish/win-x64/SHA256SUMS.txt @@ -102,7 +102,7 @@ jobs: env: GH_TOKEN: ${{ github.token }} run: | - $zipPath = "artifacts\release\hakamiq-csokit-$env:RELEASE_VERSION-win-x64.zip" + $zipPath = "artifacts\release\csokit-$env:RELEASE_VERSION-win-x64.zip" $shaPath = "artifacts\publish\win-x64\SHA256SUMS.txt" if (-not (Test-Path $zipPath)) { @@ -120,7 +120,7 @@ jobs: $zipPath, $shaPath, "--title", - "Hakamiq CsoKit $env:RELEASE_VERSION", + "CsoKit $env:RELEASE_VERSION", "--notes-file", "RELEASE_NOTES.md" ) diff --git a/.gitignore b/.gitignore index cfda857..087bfed 100644 --- a/.gitignore +++ b/.gitignore @@ -123,7 +123,7 @@ $RECYCLE.BIN/ .localhistory/ .vshistory/ -# Hakamiq local corpus and disc/container images +# CsoKit local corpus and disc/container images *.iso *.cso *.zso @@ -137,7 +137,7 @@ $RECYCLE.BIN/ *.bin *.pbp -# Hakamiq local reports +# CsoKit local reports *.repair-report.txt *.verify-report.txt *.compress-report.txt diff --git a/CHANGES.md b/CHANGES.md index dadddec..de1d9e4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,8 +1,22 @@ # Changes +## 2026-08-02 — v7 published smoke gate repair + +- Update the published CLI help smoke to the current verify contract: `csokit verify `. +- Build and stage `CsoKit.Native.dll` inside the standalone published EXE smoke directory before `native-info` and codec checks. +- Add the published EXE smoke to `Verify-Hardening.ps1` so the main merge gate covers it automatically. +- Add source guards preventing regression of the help contract, native staging, or main-gate integration. + +## Release gate filename-policy alignment + +- Move release and round-trip artifacts into isolated working directories. +- Use short fixed output names (`smoke.cso`, `out.cso`, and `back.iso`) that comply with the 2–10 Unicode text-element policy. +- Add a shared PowerShell output-name guard and enforce its presence from `Verify-Hardening.ps1`. +- Scan literal `.cso` and `.iso` names in release scripts so future policy regressions fail before build and publish. + ## 0.6.0 -Hakamiq CsoKit 0.6.0 adds the Windows desktop app, improves the CLI release path, and hardens ISO/CSO verification. This release is mainly about making the tool easier to use without weakening the repair and verification rules. +CsoKit 0.6.0 adds the Windows desktop app, improves the CLI release path, and hardens ISO/CSO verification. This release is mainly about making the tool easier to use without weakening the repair and verification rules. ### Added @@ -41,4 +55,42 @@ Before publishing 0.6.0, the release gate must pass: - SHA256 manifest generation. - Optional real ISO smoke when a local game image is available. -That is enough for the public release. Deeper benchmark and forensic notes live under docs/archive. \ No newline at end of file +That is enough for the public release. Deeper benchmark and forensic notes live under docs/archive. +## Security and architecture hardening + +- Restrict production native-library loading to the application directory; gate repository artifact probing behind `CSOKIT_NATIVE_DEV_SEARCH` and support an optional SHA-256 constraint. +- Require native ABI 2 before every native codec path. +- Propagate cancellation through deep verification, repair, CLI `Ctrl+C`, WPF Stop, and final output promotion. +- Add a centralized, bounded compression-worker policy and checked queue sizing. +- Add `CsoKit.Application`, typed operation metrics/detail lines, and a central container-reader factory. +- Split WPF operation execution and report generation out of the main ViewModel file and add WPF-facing tests. +- Build Native before tests in CI and require real native compression/decompression round trips. +- Centralize managed/native/release versioning in the root `VERSION` file. + +### Hardening review follow-up + +- Fix CLI thread-option definite assignment so Debug builds do not fail with CS0165. +- Qualify the WPF base class as `System.Windows.Application` to avoid the Application namespace collision. +- Remove the CLI project reference to Core and route compression, decompression, repair, and verification use cases through Application results and DTOs. +- Make typed operation detail records the source of rendered text and remove the legacy free-text detail parser. +- Add architecture source guards to the hardening verification gate. + +## 2026-08-02 hardening v3 correction + +- Fix WPF compilation after ViewModel/report extraction by adding explicit namespace imports and safe worker-count parsing. +- Use compressible native round-trip fixtures and separately verify fail-closed handling of native `OUTPUT_TOO_SMALL` candidates. +## 2026-08-02 output file-name length policy + +- Require user-visible output base names to contain 2 to 10 characters, excluding the extension. +- Truncate long automatically suggested names and pad one-character names without changing the extension. +- Keep collision suffixes inside the same ten-character limit, for example `Game-2.cso`. +- Apply the same validation to CLI and WPF through the Application boundary. +- Add Arabic and English validation messages and boundary tests, including Unicode text elements. + +## 2026-08-02 output-name CLI failure handling + +- Handle output-name validation failures before requiring operation DTOs in `compress`, `decompress`, and `repair`. +- Preserve structured text errors and stable `CannotWriteOutput` exit codes for one-character and eleven-character output names. +- Emit JSON failure envelopes even when early validation returns no operation data; metrics are `null` in that case. +- Keep typed DTOs mandatory for successful operations, where missing data remains an internal contract failure. +- Add dedicated text and JSON tests for the lower and upper file-name boundaries across all three commands. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8ab1062..e87ec5c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -78,4 +78,12 @@ If you have a real PSP ISO available, add the optional corpus smoke: For a future release, replace `0.6.0` with the version you are publishing. -If NuGet vulnerability metadata times out with `NU1900`, retry later. If you must validate while the audit feed is unavailable, use `-SkipNuGetAudit` and mention that in the release notes or gate summary. \ No newline at end of file +If NuGet vulnerability metadata times out with `NU1900`, retry later. If you must validate while the audit feed is unavailable, use `-SkipNuGetAudit` and mention that in the release notes or gate summary. +## Native development search + +Normal releases load `CsoKit.Native.dll` only beside the application executable. Local +repository artifact probing is disabled by default. Developers may opt in with +`CSOKIT_NATIVE_DEV_SEARCH=1`; set `CSOKIT_NATIVE_SHA256` when testing a specific build. + +The release version comes from the root `VERSION` file. Update that file once; managed +project metadata, CMake native constants, and release scripts consume it. diff --git a/CsoKit.slnx b/CsoKit.slnx new file mode 100644 index 0000000..b26db9d --- /dev/null +++ b/CsoKit.slnx @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..d8e0a6f --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,8 @@ + + + $([System.IO.File]::ReadAllText('$(MSBuildThisFileDirectory)VERSION').Trim()) + $(CsoKitVersion) + $(CsoKitVersion) + $(CsoKitVersion) + + diff --git a/Hakamiq.CsoKit.slnx b/Hakamiq.CsoKit.slnx deleted file mode 100644 index 254367e..0000000 --- a/Hakamiq.CsoKit.slnx +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/LICENSE.txt b/LICENSE.txt index f8b5878..34b940b 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,9 +1,9 @@ -Hakamiq CsoKit Proprietary License +CsoKit Proprietary License Copyright (c) 2026 HAKAMIQ. All rights reserved. -Hakamiq CsoKit is proprietary software owned by HAKAMIQ. +CsoKit is proprietary software owned by HAKAMIQ. You may download and use the official compiled release binaries for personal, non-commercial use. diff --git a/README.md b/README.md index 8e47859..821b92e 100644 --- a/README.md +++ b/README.md @@ -1,69 +1,71 @@ -# Hakamiq CsoKit +# CsoKit -Hakamiq CsoKit is a Windows x64 toolkit for PSP ISO and CSO files. Use the desktop app for normal work, or the CLI when you want scripting and exact control. +CsoKit is a Windows x64 toolkit for PSP ISO and CSO files. Use the desktop app for normal work, or the CLI when you want scripting and exact control. ## Download -Grab the latest Windows x64 package from the [Releases page](https://github.com/HAKAMIQ/Hakamiq.CsoKit/releases/latest): +Grab the latest Windows x64 package from the [Releases page](https://github.com/HAKAMIQ/CsoKit/releases/latest): - hakamiq-csokit-*-win-x64.zip + csokit-*-win-x64.zip -Extract it anywhere. Keep `Hakamiq.Cso.Native.dll` next to the executables. +Extract it anywhere. Keep `CsoKit.Native.dll` next to the executables. ## Quick start Desktop app: - .\Hakamiq.Cso.App.exe + .\CsoKit.App.exe CLI help: - .\hakamiq-cso.exe --help + .\csokit.exe --help Version: - .\hakamiq-cso.exe --version + .\csokit.exe --version ## Common commands Show CSO information: - .\hakamiq-cso.exe info ".\game.cso" + .\csokit.exe info ".\game.cso" Verify a CSO file: - .\hakamiq-cso.exe verify ".\game.cso" + .\csokit.exe verify ".\game.cso" Deep-verify and calculate SHA256: - .\hakamiq-cso.exe verify ".\game.cso" --deep --sha256 + .\csokit.exe verify ".\game.cso" --deep --sha256 Detect an input format: - .\hakamiq-cso.exe detect ".\game.iso" + .\csokit.exe detect ".\game.iso" Analyze a PSP ISO: - .\hakamiq-cso.exe analyze ".\game.iso" --psp + .\csokit.exe analyze ".\game.iso" --psp Compress ISO to CSO: - .\hakamiq-cso.exe compress ".\game.iso" + .\csokit.exe compress ".\game.iso" Use the fast profile: - .\hakamiq-cso.exe compress ".\game.iso" --profile fast + .\csokit.exe compress ".\game.iso" --profile fast Decompress CSO to ISO: - .\hakamiq-cso.exe decompress ".\game.cso" + .\csokit.exe decompress ".\game.cso" Repair or normalize readable input into CSO1: - .\hakamiq-cso.exe repair ".\game.cso" -o ".\fixed.cso" --profile game-safe --deep-verify + .\csokit.exe repair ".\game.cso" -o ".\fixed.cso" --profile game-safe --deep-verify Profiles: `game-safe` default, `compat`, `fast`, `smallest`, `archive-smallest`. +Output base names must be 2 to 10 characters; `.cso` and `.iso` extensions are not counted. Automatically suggested names follow this limit. + Full CLI reference: [docs/CLI.md](docs/CLI.md). ## Exit codes @@ -86,11 +88,17 @@ Full CLI reference: [docs/CLI.md](docs/CLI.md). ## Limitations -Hakamiq CsoKit focuses on PSP ISO/CSO workflows. +CsoKit focuses on PSP ISO/CSO workflows. ZSO, DAX, and CSO2 are readable input containers; CSO1 is the default output format. Verification checks file structure, not emulator or device compatibility. ## More documentation - [CLI reference](docs/CLI.md) -- [Contributor scripts and release gates](CONTRIBUTING.md) \ No newline at end of file +- [Contributor scripts and release gates](CONTRIBUTING.md) +## Architecture and safety + +The repository is split into `CsoKit.Core`, `CsoKit.Application`, CLI, and WPF adapters. +Production native loading is limited to the application directory and requires ABI 2. +Compression workers are bounded, and cancellation is propagated through verification, +repair, and final output promotion. See `docs/SECURITY_HARDENING.md`. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 78c6ef5..13362c0 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,4 +1,4 @@ -# Hakamiq CsoKit 0.6.0 +# CsoKit 0.6.0 Windows x64 release focused on PSP ISO/CSO workflows, WPF usability, and release-grade verification. @@ -40,7 +40,7 @@ If NuGet vulnerability metadata times out with `NU1900`, retry later. If you mus The official GitHub release provides: - hakamiq-csokit-0.6.0-win-x64.zip + csokit-0.6.0-win-x64.zip SHA256SUMS.txt Download from the GitHub Releases page. \ No newline at end of file diff --git a/SOURCE-MANIFEST.sha256 b/SOURCE-MANIFEST.sha256 new file mode 100644 index 0000000..4fd6429 --- /dev/null +++ b/SOURCE-MANIFEST.sha256 @@ -0,0 +1,260 @@ +83c222af1fe6e8a696852842dcc2a333b712d7f8e7a52d253cf1947eb75d0696 .gitattributes +09667751691de0e0984a30ad9c0517c9cf1908f6f7bbcf1d6ada558305eea50f .github/workflows/ci.yml +ec199855c0fbe73a3871363760991467d71f476c7a33f2b3dd51d40871f735c9 .github/workflows/release.yml +694fde6f4a55f0ae724f83e981e929db32e1ece1a813b0e5edadf87bd6fead21 .gitignore +d56402cce282880005ac828a4f54d87b5034a2dadd77106a03ba8b22f433b6ac CHANGES.md +78a9a8ddb6d7710bf28ccce1273e1096d946b3635f676acb5326ac853dcecff9 CONTRIBUTING.md +b589f99ad50c9ad872cfcb8f534218ff9f15795a5d2c8b0bb414980c04975dda CsoKit.slnx +94b8ed7dad0ef87941504b4e36317053b2139426408936c4e2f39530043e741e Directory.Build.props +7837b303799c6577bfccd56ea2de547203d4fbf5e63395edd66f66c59cb32921 LICENSE.txt +a47978a5202685045e70d851e01bfdfc7c650f70ef900c2e792e1e351ef030ce README.md +e76f95da340776c6b22df4343c6e83d586abc5849e115d2a2210296ed49adb59 RELEASE_NOTES.md +86b8001ad913ef0cc8a24a89ed2a8e8a10f96575d90f5578dbd9125fa98158a5 SOURCE_FILES.txt +46c3a139f30b02d6408101c245fded884db955813e5a3f754e1b6b0bafc57c2c THIRD_PARTY_NOTICES.md +97a5d6e540a6120d09c39ddb667e0e8e2bac7fcc2ffef813b82e08fd60365bce VERSION +13cd8603ecc7b23ba8a1286cf9a188bfd6d97689c8a184ccf142f9a0ae6b115e docs/CLI.md +8a6efb099f97fb79905164eabe3a1c98c4a672a69e908d2c13a54acf9c0dc4df docs/HARDENING_IMPLEMENTATION_REPORT.md +690904fb562259bb92ce72b34ec7f56e445e1c7eff9f56e76bcfaa58b5726538 docs/NATIVE_BUILD.md +6db091f1350664ecfdee5b1d86bbc03da2580d662ace294999c5eb26c92ca73b docs/README.md +4202b423bba113e0314fed1414b633dd2de9e127ac09933bf9c21a77177c5b43 docs/SECURITY_HARDENING.md +2172de5869b1e082a938baeed3c4e57f2de75050925e78b0024816d6bab91bec docs/archive/CHANGELOG_FIX_NOTES.md +9c100eed8816ac61bb49814146c81742a604886bbec103d2bec7962f14ed0c7b docs/archive/R1_ARCHITECTURE_REPAIR.md +e6e778d21267ac800c1c311a75bc47526257dcc1319b7c35f520376c6729e24d docs/archive/R3C_RELEASE_HARDENING.md +ac73bd03c853aaef89fa6d0dd51ffd6b935ef73b17459f3c4280dab4c75ebb93 docs/archive/R3D_BENCHMARK_TRUTH.md +1349344daae36722dd3d04b96062193151b07e31267e3603fe649b1823db28cf docs/archive/R3E_REAL_CORPUS_EVIDENCE.md +622cd19631635bb08684110206aa3dec35083d1baa179883ddd167b5509f3375 docs/archive/RELEASE_0_5_0_SCORECARD.md +5e4c694728b2e055f8c0d80ba812875b6c87d03b02a599015d67b98b24af771d docs/archive/RELEASE_SCORECARD.md +f59002da509cb542250a5783b44747e763632fb63fa1fc7a13a32a407ebfc1e3 docs/release/RELEASE_0_6_0_GATE.md +4b1148a62780adfaf9f7d34f1fd795ffc0299d6bc41cad4057c0acf8b1a460ea native/CsoKit.Native/CMakeLists.txt +c22d0676fba3d95603d2b368ca94444c0b222e745b1fd2d749b85908f6319e18 native/CsoKit.Native/include/csokit_native.h +3f826677044ccac3f240c402e3ab2059ed916d5299ef1dcb78ffbd4b27327db4 native/CsoKit.Native/include/csokit_version.h.in +8da2870fe1221ca70af3920e9abfbb6e35578235bd09341470bc5a0e7f543653 native/CsoKit.Native/src/csokit_native.cpp +675fc1c25ad23d5e14255152262598b591a6e3fc65f0871655f5f6585f120acd native/third_party/zopfli/COPYING +fcf520edfbd8011d0710b3c8bf4db334e5902bd7e217bf4ff406db3d881699b2 native/third_party/zopfli/README +3056afd38dd01c7acb688df7bc365e9e3055cc8d5b548b394c3f5ba6147f7ea5 native/third_party/zopfli/src/zopfli/blocksplitter.c +3db4f4b63fa25f4c135c8438d880a4be9ae7403b40a4ed1a1fd5f461be7dda06 native/third_party/zopfli/src/zopfli/blocksplitter.h +77c7e378af671a2113306a0db5a15630a99b709a4299ba2cb411b0820d2e1c3b native/third_party/zopfli/src/zopfli/cache.c +1c041868ad624b37736b52db0af81562a6c0fdb163f459315ea596e8552770a8 native/third_party/zopfli/src/zopfli/cache.h +4d219194e6b6a6fa76a3583e0bfbff831219515ed589784dea403d1553ae6c1b native/third_party/zopfli/src/zopfli/deflate.c +fa62fff6aab5e047412eb9a46e7972c91a17a9bcd230adddd4ce44df2a00e8b4 native/third_party/zopfli/src/zopfli/deflate.h +8e24e6259ef6fef05953ad9a3471fed9f421dcea8edda2135b4fb9a979b115b9 native/third_party/zopfli/src/zopfli/gzip_container.c +8d687a588f5638965e4881802a30a547601b32ea7cb686218afbfb25ef1f0f42 native/third_party/zopfli/src/zopfli/gzip_container.h +9d6e603c2954826049ff13e13bdf0499fc3d78cff01a6ae0429ccdf23dc00c36 native/third_party/zopfli/src/zopfli/hash.c +51ea819f5e8d64ca6ee4498abc7b57a1053d93fd21df14b8c93a20c9186be4a2 native/third_party/zopfli/src/zopfli/hash.h +e5555b9cdadfd427f4903457ac28452b089db899021bffe66fdc653be793683e native/third_party/zopfli/src/zopfli/katajainen.c +eaf4b6da83c24bc341612f8ccbad2b10287bc1242e2b4a75b950fdaf805e2d69 native/third_party/zopfli/src/zopfli/katajainen.h +dddafaafed3cf36cd046cbe14960606a56a32380dab9084cdc31f70119e9dd29 native/third_party/zopfli/src/zopfli/lz77.c +9d3ac03cfb94c2b1a1eb6d4bf9044dc4f86436f062699828bce8a103fb8ef12c native/third_party/zopfli/src/zopfli/lz77.h +2584b9889f6b8f35e4bdf312548904d64416cac78d21b2ffd24c97b5f13f8b0e native/third_party/zopfli/src/zopfli/squeeze.c +47db13efe62c0876e4ea53004885b96327f40cf0b9c6107a74f9ef94c1e0235a native/third_party/zopfli/src/zopfli/squeeze.h +2ab04edd4c135b46a8255ac766040c37a5f10c3b2f908a255e68db3d7c53056f native/third_party/zopfli/src/zopfli/symbols.h +93c9e603a494a7e7b075dc92b89ebfd6813fb229508a7acc97ebd91ad956d8f2 native/third_party/zopfli/src/zopfli/tree.c +396977e269ee143a0c5fa3393fe002f78a605c525f35a9e4fa5ac2250bfd0a07 native/third_party/zopfli/src/zopfli/tree.h +db1a6fb953b284a5c2df64b8ceda5943ff6059a6d4a83148e6f3ac04bc5e57a5 native/third_party/zopfli/src/zopfli/util.c +72730de4d23c65de01057c8c8167bb90364999a6914c1520c20c4837afa5db73 native/third_party/zopfli/src/zopfli/util.h +72d331a099559eafbc4b49d1aa1101f8dbf228ec89920e63cba49a40ade416c6 native/third_party/zopfli/src/zopfli/zlib_container.c +7744d8afea2acca76c8e9f823c4f8df3c7545ec8c9fbe0ea14b67d35f5f7c52f native/third_party/zopfli/src/zopfli/zlib_container.h +9cff9d2ed11be71b8bc82aed0afd2ed47391609c138ae2bb3dc18730e62ddcb1 native/third_party/zopfli/src/zopfli/zopfli.h +cca1503d387c6723b905149830794bff15cfc7e6e1c0bd3d49f2ce7fda53abc2 native/third_party/zopfli/src/zopfli/zopfli_bin.c +2464d1493e1a9ec503fbac5bde81987b8507d81b34d2e596e128a93204d8486a native/third_party/zopfli/src/zopfli/zopfli_lib.c +84f0ed4f3c3bc5b7a4bd3b428c33c47fff5110bc0b7bbda4ba9df7b2b3ec7156 scripts/Build-Native.ps1 +a35066440e494f9bba232dd743a174e7be5311e591c5533334f4dd7fd5ab2c0d scripts/OutputFileNamePolicy.ps1 +5aaf77a4f69d7786649a108b8719cc80e4e5499354c3752aa5861d6c87b0f47d scripts/Publish-Release.ps1 +d8000002589caa379e607cb91aa6233476322b1bc7ade0032317cb29e0d2081b scripts/Publish-SourcePackage.ps1 +413bc4f68cf8a1420e736183ec93d5a8299571d3dc9b7107c76c3d850bc32e93 scripts/Remove-Utf8Bom.ps1 +721223faf51b16d27d2955acb411f2eebc0d3823f7ae16b8dc6585c9d06403df scripts/Run-BenchmarkTruthLayer.ps1 +e54578882747486bafe17deb80828bf93f828f175b7c6641aca40abddea7d5e6 scripts/Run-FinalReleaseGate.ps1 +3cf088679c34cb06a044cd910a75760cfcdec9c4b5d7507775081683d2273e3f scripts/Run-OfficialReleaseGate.ps1 +9ce98993d496a3cc1006968e14b621ec8ef6097498614ad71a3ceb3413cec7dc scripts/Run-ProfileRoundtripMatrix.ps1 +3fad0591340a947e86481aa883a9ec943f3f273c4d47e1c7386373ed64e62a73 scripts/Run-PublishedExeSmoke.ps1 +11c0a75f4103c119514666e0ff0ffc06b49949fc700a0e422c2e6e12a446cb6d scripts/Run-RealLocalCorpusGate.ps1 +9f047a9c826004c25268c5de7dac82e33aaf132b50f49043abee7520d044df46 scripts/Run-ReleaseGate.ps1 +6eaac31f8d25835ba79eb35b0938f08c4db5b1925aa957b2869be5c3015176ae scripts/Run-RoundtripGate.ps1 +c76b7ebcf8f62071e041f5de7679b958e70f7070bcbd9666d79f72a4597dfda2 scripts/Test-RepoTextEncoding.ps1 +6c8043ce2d818c76118fb4275de9afa625eeab9a9805dc463d03310fe3d45c00 scripts/Verify-Hardening.ps1 +c1a329c768b4757d3960914e46221e22279b0fcac276a818cc34a93e23d35ce7 scripts/Verify-Release.ps1 +2ac7fdf01c304542406356b6c6cdc1a557d84ad844552961866f07962071581d src/CsoKit.App/App.xaml +b34df67641b151d24cd8d103b14ceb9913a08bf96a4c251a5ccd99b7995fd1f9 src/CsoKit.App/App.xaml.cs +8b062933e799689e343c31b5d1e44e7c6587d48ceeb9d899cf66765977993342 src/CsoKit.App/Assets/Icons/advanced_key.png +ffe1f054ea41493518ce258b346d662b929ac363177fd12716b0f61be36540f4 src/CsoKit.App/Assets/Icons/csokit.ico +ad88db1a9acd9867478d21dde0132a9d0e8179c46af6e385093488b7e9f3b904 src/CsoKit.App/Assets/Icons/csokit_32.png +d04ecfc93ff86c44f6fc39e35945e3d8a7648ba8fcd97a2635920df2e88893b3 src/CsoKit.App/Assets/Icons/status_error.png +644faffc659fb1e6778cf5290022fbcde177952c66881848e6380ed91211e878 src/CsoKit.App/Assets/Icons/status_success.png +760dbc493f4dcecbbd55573d095ed9685038aa100715c55aae1306870d44fc43 src/CsoKit.App/CsoKit.App.csproj +b9e950030953a7f673d3d9a538008907d987636c6bf5b05488df9fa5e215864f src/CsoKit.App/Localization/ArabicUiText.cs +4d64f244c859cfb8e3faeea4eccb0dcb42f10e3996e73618e3d578edbb22a8d9 src/CsoKit.App/MainWindow.xaml +b3317763fc6e197f679da2e253e02f6b547c339fbd39d51a1b9de4700361f1f6 src/CsoKit.App/MainWindow.xaml.cs +b322a29589c4a11e41566d62dded83bf684bdb099507643fb923dbe29cffab6f src/CsoKit.App/Models/UiLogEntry.cs +56ad9466818c37b02552143c96bd25c45b3124fd1fa39417e9cab149e619f9ad src/CsoKit.App/Models/UiOperationKind.cs +dfd131c480ba8c39b986be904336d8e61db8cffee70aa56abc00c9e6b44c084b src/CsoKit.App/Models/UiTaskItem.cs +9c645fb2ae2efae5e9c42e213320eeffe370f13f7cabafda83787b1498957965 src/CsoKit.App/Properties/AssemblyInfo.cs +2a111c2dcbb5d4ac516c7cae5c67125104f5a31cdf4047034061d94c63ae394d src/CsoKit.App/Services/OperationReportService.cs +ab0b7b62c282cdf300c592666175ed2eb31499db6c448ab43f0621106fe9c5df src/CsoKit.App/ViewModels/MainWindowViewModel.Operations.cs +02c7e365c2b119feedf39d88276b04887139f7041025ad7bf4a0bd1c523ca108 src/CsoKit.App/ViewModels/MainWindowViewModel.cs +283224e67125a2dccc0d213f0788a76c11c86362db928d9581ab185ca1022a02 src/CsoKit.App/ViewModels/OperationSummaryViewModel.cs +472859d48e02aeac35be04a2c601d2af0a155e81c7d3ac0fc83390c2d47403c6 src/CsoKit.Application/CsoKit.Application.csproj +8b4fa40bfbe0933fddf4ed47a8179f4cef925b6baef720898dadf618597bde09 src/CsoKit.Application/CsoOperationData.cs +dfae0f8c558bafb32fd23f86d87b7cc4b58fdceae6f21b198c80f7bdc0338b5c src/CsoKit.Application/CsoOperationDetail.cs +17a2a190a3381da67ff909dac9c5bb07b461f9d90539528f860451bd4dbc03d8 src/CsoKit.Application/CsoOperationDetailsBuilder.cs +c3161e14ed1689bbe31bfbcd919e35e0dded2ead03a9dc5141df049c73850f19 src/CsoKit.Application/CsoOperationResult.cs +65dc7a9fdc845a59ac02ce86437ca9efe15764460dd35fdbbe4c7de69390c127 src/CsoKit.Application/CsoOperationService.Verification.cs +07eaa67f591ec31ae49dd7dc0a12ce9f26e9905b728be39890aea9246510bbd0 src/CsoKit.Application/CsoOperationService.cs +1b0523322c48e5f4477d2a76fb67d6c6c92ff016ae64d9ac27390fb414c7b430 src/CsoKit.Cli/CliExitCodes.cs +ba85c32a11a8102bed0e483aa9de3389c6e085e8a487342b84e7d8871c3de91c src/CsoKit.Cli/Commands/AnalyzeCommand.cs +4c998fc32006b630da158306d0d6b84dea6b4bd315f63780f9e132214fa6713e src/CsoKit.Cli/Commands/CodecsCommand.cs +ce9da41cc3da46bbac0d229b23d3d07e4200dabdbc9956f5b75c95d47929a9cb src/CsoKit.Cli/Commands/CompressCommand.cs +fed2ece8b83e0dfb4e874f8ee1a25142b1368d536b6f0250f66927408fbb8847 src/CsoKit.Cli/Commands/CsoCommandDispatcher.cs +1369fbee172aa573b612f7ed1c9fc9ddaa366af3201c70e16a657c61f4fcfce6 src/CsoKit.Cli/Commands/CsoCommandError.cs +98e98344dc715d92841e1cc29d1953b1d9e79c19241a3af94813d0f1b71201a9 src/CsoKit.Cli/Commands/CsoCompressJsonContract.cs +70aa3ce63329d2cde0b6520609f22e9700966031778b2313ec1ef9f2e249bb19 src/CsoKit.Cli/Commands/CsoProfileOutput.cs +a1ec171e0b3ebfb57f9ead08aca9023001e01911187a0bff8bcdf133f5368923 src/CsoKit.Cli/Commands/DecompressCommand.cs +063a02a26b9993e848d3c30f770f57ea1855d9a6042fbffdae3725db9f05b149 src/CsoKit.Cli/Commands/DetectCommand.cs +2e5935de82e180933f5f0cf143ca163f9dd47b7a9261d0e707efb7abc873921d src/CsoKit.Cli/Commands/InfoCommand.cs +c3225a65d30cd64167f420ac524c8851839149317c52f5c288b70c3fc78af16b src/CsoKit.Cli/Commands/JsonConsole.cs +2ecf5d87cf25c875b5098869b0babc78b9ccca649fdedc0b8453395ed4cfcef0 src/CsoKit.Cli/Commands/NativeInfoCommand.cs +a0aeb3b5aa497d4689ac5268450cedbc840f523b3596f864345cf951c67ddd66 src/CsoKit.Cli/Commands/RepairCommand.cs +b7ce0b2b7bde5a2d045478a19e4a02121a372fb577682f01bd5277267633b8be src/CsoKit.Cli/Commands/VerifyCommand.cs +abe3404faecd5ed71c64d4178b659b306505a26ca3449abfbcb1e4bd6468204e src/CsoKit.Cli/CsoKit.Cli.csproj +b3561a98166a588119e68ebf756f1689aaf6df9eedfb9a579f152e8ecfd64878 src/CsoKit.Cli/Program.cs +bcaac708370d25a6d0cf182ba90a9be42ff455c5c123ec316d7552171816a66d src/CsoKit.Core/Analysis/PspIsoAnalysisResult.cs +455e3fccfc1d14c7dcea4cb65fb2b2f9420cc8c6757778086e2b8c5375a2f1e0 src/CsoKit.Core/Compression/CsoWorkerPolicy.cs +b15818c8b6d3a03aa6df80ddd35564390888e13cb7ae8c664f9d6359e56ed757 src/CsoKit.Core/Compression/Trials/CodecTrialCandidateResult.cs +32c91e912a4c8aed5063ae248676f26ea71c12cfc8352da20b09d1cfeea295e1 src/CsoKit.Core/Compression/Trials/CodecTrialDecisionMetrics.cs +b8f90b197ec2ef3b45257d66ca0f679158b564741412b0f99ba023354cd7c4e5 src/CsoKit.Core/Compression/Trials/CodecTrialReport.cs +69910633e8953a24a6e52e89729356d10f7d370c1edffa713a5e29bb51fbaf00 src/CsoKit.Core/Compression/Trials/CodecTrialSummary.cs +4e4247f4e0f2638454e9681b09d6f020ab70152fc211017e52b180d7e3a3da3c src/CsoKit.Core/Compression/Trials/CodecTrialSummaryBuilder.cs +9c4f985b1f906eb62e5f34b8e34617bf5193052bfb7a9c805db0a27ad8d6e187 src/CsoKit.Core/CsoKit.Core.csproj +0f5f0341909c4d1b98383a49cdcb801ef56e6cb73a5f5d5c4adc5b4ff4088a41 src/CsoKit.Core/Formats/Containers/BlockContainerReadException.cs +306273e52118207a00d38203a9f0a717236f63cf8e58a60353b82adc1a495d21 src/CsoKit.Core/Formats/Containers/BlockContainerReaderFactory.cs +57808b815dfaa014b1ceebe7a07efa2c86113bb5065a2268fbc0c1579cdfbb5d src/CsoKit.Core/Formats/Containers/ContainerDeepVerifier.cs +440b2fae9bb984c2d91f42d089034121f98e32db723f4f64afaba911c3a961ec src/CsoKit.Core/Formats/Containers/Cso1ContainerReader.cs +84dc142554fc154d0bba3ce7c1fa6237292df42d29edc42a309e0853e346defa src/CsoKit.Core/Formats/Containers/Cso2ContainerReader.cs +a5476b5324b571d4cef4caf749a46c23d077c7d8b2e741512a540d699a9ea9db src/CsoKit.Core/Formats/Containers/CsoLikeContainerReader.cs +0e73a278f5c072edb0a54c07a6a0453ddbc8b80aefd83d9533f70696007c349f src/CsoKit.Core/Formats/Containers/CsoLikeHeaderReader.cs +80d4e2b39ea2f32833c65dfab134abbdc91d848639de0618ae47933e387a64c9 src/CsoKit.Core/Formats/Containers/DaxContainerReader.cs +185fb647a5924253015f3bedf3a9e77071b8ac0f8214e879c744363b83eaeced src/CsoKit.Core/Formats/Containers/IBlockContainerReader.cs +af85b96d796ea951f1fae26a6693993bef7ea1975280beb4110a8a6f1186826c src/CsoKit.Core/Formats/Containers/IsoContainerReader.cs +1e81021bb0a6e0f51b7960031c929dd58e2686dd00451e72618f3cb316cf6650 src/CsoKit.Core/Formats/Containers/Lz4BlockDecoder.cs +d148b35984daf78a240f226e819a91f1aa84862808d40dc58b9e24aa8c82966e src/CsoKit.Core/Formats/Containers/ZsoContainerReader.cs +ae11939aa146b14d00d7b9fad5b8135287e49624eee5c5942176565095c4ea76 src/CsoKit.Core/Formats/Cso/Codecs/CsoCodecKind.cs +ec49a9b011977a3938c1bec1b251ea4eef4edd5bee29a681e4fdb09e1f62d75f src/CsoKit.Core/Formats/Cso/Codecs/CsoCodecTrial.cs +b3b64da7651ff3b2641ec6d0ff08587ad08f7b1cb84b20ddff044389e3d02cb1 src/CsoKit.Core/Formats/Cso/Codecs/CsoCodecTrialResult.cs +ef2977adef292be5d6a9223ddc485f082c6b498285b2e4ee6687b7b4c950a1f9 src/CsoKit.Core/Formats/Cso/Codecs/CsoTrialEngine.cs +96af06be69a30a72512a18e21c07de37179bdc579a10ac557ffc1663a828fdf6 src/CsoKit.Core/Formats/Cso/Codecs/CsoTrialPlan.cs +18e61e3332ad7f3ef012f3972600d59f496b7ba8dd0cc1465a282f35587984b1 src/CsoKit.Core/Formats/Cso/Codecs/CsoTrialPlanner.cs +bc90849095d783b3e085f1859a3d389e8a29391ed0b992989cb8fa794862f2f3 src/CsoKit.Core/Formats/Cso/Codecs/ICsoCodecTrial.cs +bd2b72733a62fe7300a5841c42e3bafe2f0d5e9fe12d39736400659ee76d507e src/CsoKit.Core/Formats/Cso/Codecs/Managed/ManagedDeflateTrial.cs +da5826f50824345f07cc446cdf0e816cdcdb9a4142094c625c478e2d296e0cb2 src/CsoKit.Core/Formats/Cso/Codecs/Native/NativeLibDeflateTrial.cs +f8521541742be6fd4d969f278a351ee30dce850dc1b6e32693520e4e96f5b64e src/CsoKit.Core/Formats/Cso/Codecs/Native/NativeUnavailableTrial.cs +163e1ae0bac9b3575accb5f14717286398f4d31f7657779139b4f322b576efa9 src/CsoKit.Core/Formats/Cso/Codecs/Native/NativeZlibTrial.cs +4ee862858e39c08d0af267e89d161ff6686d259a414b7f35f0e539f7c8b1cd4e src/CsoKit.Core/Formats/Cso/Codecs/Native/NativeZopfliTrial.cs +a0c0bb9a8894923d90d2b490dd6c95079147a231572f6e3b5ca4527f3aa920b6 src/CsoKit.Core/Formats/Cso/CompressionMethod.cs +7d93a116ba441e221251833bb016ed7422793ef0cc11a43075965347a877f659 src/CsoKit.Core/Formats/Cso/Cso1Writer.cs +19e576da97133c6d30b429b431f16aa5ecd4fd25bd6c8cc35749c8a984eb4d78 src/CsoKit.Core/Formats/Cso/CsoBestCandidateSelector.cs +c7325a535e674d0a074e12605e25ac1866d1869ec0b252654a56939c0a03f4d7 src/CsoKit.Core/Formats/Cso/CsoBlockReader.cs +cd11a2e4775f0fd3985ac8873c74f23363d185fb7c792a7771a9e1fdbda8b0bc src/CsoKit.Core/Formats/Cso/CsoCompressOptions.cs +4b13804311f4b502d2d258c59129100e8447874faabc9c827be188eeba1cde51 src/CsoKit.Core/Formats/Cso/CsoCompressProgress.cs +33ac5cdee19aea81487ee99d1c54a75f61eb809a3a952d3812530133686ea49a src/CsoKit.Core/Formats/Cso/CsoCompressResult.cs +79307f6efe0fd073f20f0f87a707eee26d77e541857caf5e8f5acef9f64765ec src/CsoKit.Core/Formats/Cso/CsoCompressionProfile.cs +e6ab1ad1a6bd1301f1495f9091ffdba2f3f02d6324c091e93d7045240c6737ac src/CsoKit.Core/Formats/Cso/CsoCompressionProfilePolicy.cs +b6c9e30c4679614faff5674ae05549842aa2261e33feb1a4cfeba71da1f6b19b src/CsoKit.Core/Formats/Cso/CsoCompressionProfileSettings.cs +fb2d347a55d526f268d2ea208d5bf3dfab70ff3f6eee1f838f2613630f385be0 src/CsoKit.Core/Formats/Cso/CsoCompressionWorker.cs +cee9f2d5068371df605205b789775a9cf5efceb3fffe1b5f15d361a6d775474b src/CsoKit.Core/Formats/Cso/CsoCompressor.cs +d7a6852f72a5d90b8cafc30b8d2d74833426e6905902462c1abec80a52b3b95c src/CsoKit.Core/Formats/Cso/CsoConstants.cs +7629f9f78ecf32f4ca6837986b588ffaaa43dec9724ef3829b4f1eaa58c5d63c src/CsoKit.Core/Formats/Cso/CsoDecompressOptions.cs +8c3719d9bc2d7871cb8d685646c332a6473a4b727dfe6f5e70ee51f78851ea25 src/CsoKit.Core/Formats/Cso/CsoDecompressProgress.cs +5764ed5052e9a81789851ac460abdf1c2a5cb90029045522df143dd7d1c248e5 src/CsoKit.Core/Formats/Cso/CsoDecompressResult.cs +7c122bfa80b9e9903bb3d790db95381083ea9fb769da092f5db2f5b1209481cb src/CsoKit.Core/Formats/Cso/CsoDecompressor.cs +7c2ffba9f7ebe3213a9692b4d49203f3ad87dade5c59e6797affd897a76160d7 src/CsoKit.Core/Formats/Cso/CsoDeepVerifier.cs +0bba1cb45d1e734a259b9cdf2e0c9256bb5f1261eaae5a7e9e95cac0e7938c27 src/CsoKit.Core/Formats/Cso/CsoDeepVerifyIssue.cs +4e863d2c109033322f24c2a85c8aeb9c30319762d8d12fe652f004caf6e242cb src/CsoKit.Core/Formats/Cso/CsoDeepVerifyResult.cs +f41996f8ca403070eba9f94cbc26958f3d518705a6932bb353cd4b8aa34749de src/CsoKit.Core/Formats/Cso/CsoDiskSpacePreflight.cs +fab30644f72a43dcb97036e8c0a942048ac94a6eaada96aaa9768200b8ad94bc src/CsoKit.Core/Formats/Cso/CsoDiskSpacePreflightResult.cs +9a5f196421a989f1de860205e9be353c2158229ccb8505e08af1cc089dc0f022 src/CsoKit.Core/Formats/Cso/CsoFileNamePolicy.cs +07ca87cd07b4692ec35b42eb3c8dd84d67a55b835c40bd0f8dd8e8f193a32103 src/CsoKit.Core/Formats/Cso/CsoHeader.cs +6b2a198ca0dbaca4061366e0245babd2459ed3d72536bb5b51ec7034e432b29e src/CsoKit.Core/Formats/Cso/CsoHeaderReadResult.cs +486bd13b6bd12c957b9a60db3ce8380012d4b38c9b2a0a95e514c08e4b6fab9e src/CsoKit.Core/Formats/Cso/CsoHeaderReader.cs +57ae70ce0b3c24250412acd8bf9b273f38c1c0d59c0425526c19584fc4fdb8c6 src/CsoKit.Core/Formats/Cso/CsoIndexBuilder.cs +56eb03080e24b20c8f08f941d9718e5f8fe2fdb87b6ba5a3dfdf7871bd38568b src/CsoKit.Core/Formats/Cso/CsoIndexEntry.cs +af4452dbd6cf8b04789729b009be7414be3cd3db493aefd9679c85606ee9e75e src/CsoKit.Core/Formats/Cso/CsoIndexReadResult.cs +45729ce84ff621ffd25f4e1d10ac395b26d22d9c16eb28c32be764658a6beaed src/CsoKit.Core/Formats/Cso/CsoIndexReader.cs +9f6e4b5819ebeb8ac63e47c41812f347885e631351ad1647d89076a76d82a844 src/CsoKit.Core/Formats/Cso/CsoIndexShiftPolicy.cs +17eb0920ce1f3b58d8278e5a00868e97b6c5ecd8c9bdc2b413378dc71615a754 src/CsoKit.Core/Formats/Cso/CsoMeasureEstimator.cs +9b3b0e7102005ee3b7f4e8b3bb4f5f65bd476042ce8203717db2dc21fdce0d53 src/CsoKit.Core/Formats/Cso/CsoMeasureOptions.cs +6bbbb685383cf6233591523a5ba22cd817154060701d28c4cb3630ef55ac26a8 src/CsoKit.Core/Formats/Cso/CsoMeasureResult.cs +45a88e1089bcee4dd6c9789f7e0f95fb5b82c80a315fd760c9fd14b13b118928 src/CsoKit.Core/Formats/Cso/CsoOrderedOutputWriter.cs +6b8cb4e0bf2fd1e33ed69797437c301083fe45a000c35bdcb5b5b863f285f3c2 src/CsoKit.Core/Formats/Cso/CsoOutputPathPolicy.cs +9ea452968f2cca0b3ee965a00f6229f30f4f43e577a1f5429678bc7116cabf1a src/CsoKit.Core/Formats/Cso/CsoOutputSafetyPolicy.cs +16b9e88f2dd77632d48f97eba07e4967616db4eb1ba2507f245c05d666eb55bf src/CsoKit.Core/Formats/Cso/CsoOutputSafetyResult.cs +b325b79d1bbc119aee42cf4d75de5188411babd4ad1da5720ddfe1f53f66cdc5 src/CsoKit.Core/Formats/Cso/CsoRepairMode.cs +3d4674df7814bcb6d784c3faad65c247d9222422c71a32ac5ff6b4718f506da9 src/CsoKit.Core/Formats/Cso/CsoRepairOptions.cs +2859f324fc31aa2b2d4eef294a69b8355099b141f46cfee08f183bf537ed46c0 src/CsoKit.Core/Formats/Cso/CsoRepairResult.cs +6bc748311dceaac82313efb60bbe1b2c353bccc5a6309bc9c9e4709bc60db6fa src/CsoKit.Core/Formats/Cso/CsoRepairer.cs +79ec13430681af1d7798797dd312e2dfeea9cc1c48adabd1dccc2af8bebd59a9 src/CsoKit.Core/Formats/Cso/CsoVerificationIssue.cs +950aa387eb2723e0e2391de92785ad3ec564632b19ed6cec09f5389025118592 src/CsoKit.Core/Formats/Cso/CsoVerificationResult.cs +955c4030f4bef6ce9da4c796589c39dbba4d962eb608e9b053084a81aa664f2f src/CsoKit.Core/Formats/Cso/CsoVerifier.cs +a00449ded5a4fa4c58550c1ca4e677ff7acc00ca920cf6d12b3cb99271ebb9a0 src/CsoKit.Core/Formats/Cso/RawDeflateVerifier.cs +16caef1410b1b452e6653660cd11797d17c9127ecbf53fbffe4c23184dc9a62f src/CsoKit.Core/Formats/Cso/SectorJob.cs +cdf66da58ecd5dee15fa46620701608fbca67546c6f107438e27c202589dee2d src/CsoKit.Core/Formats/Cso/SectorResult.cs +a5d21c8c7c81ecb7ade03448d4bc881b7e6e7a8623d1d485620d9a3dec7fac16 src/CsoKit.Core/Formats/DiscImage/DetectedDiscFormat.cs +df171c7440cd3ed360df6ec62ea87f405975ee22003c9808586bafa1c90fb5a6 src/CsoKit.Core/Formats/DiscImage/FormatDetectionResult.cs +ad8c990fe84d1b112925113f144845a27dc9b9295a31beca7e4b0d5f17ef56c3 src/CsoKit.Core/Formats/DiscImage/FormatDetector.cs +bf8c0e532c7969b60ee8d0cdbf1951cc079e33ca0b0b73d58f0d2189d084784c src/CsoKit.Core/Formats/Iso/Iso9660Entry.cs +36e4f4b0ecbbc18562ffd2b8615837925616c94c455a88ed865057e5d8bf9547 src/CsoKit.Core/Formats/Iso/Iso9660Reader.cs +a02ee5f946e44f2ba58a5a94bc5abc8dc21c0ea2d74c63702550bbae7b956129 src/CsoKit.Core/Formats/Iso/IsoAlignmentPolicy.cs +0da1d2490a7c3d820e4c34c61af278ca20b0e06cd9a2b1e31c5d99c3b55b1ced src/CsoKit.Core/Formats/Iso/IsoAlignmentResult.cs +7dfbf95c8d0d37c3e33709f0c0088e4be102b06212baf27d7ace8cfc007ddf1d src/CsoKit.Core/Formats/Iso/PspIsoValidationIssue.cs +d895996a3a3be824c44c23991f2e54b8259aad10dc3ae09cad85aacb76f072d8 src/CsoKit.Core/Formats/Iso/PspIsoValidationResult.cs +ec68ce9e588685935bf9a274e8f36c345e227be9fcbaf256336f82a2b81def91 src/CsoKit.Core/Formats/Iso/PspIsoValidator.cs +59d4502d03cef71dbf35c0c8d217b62245f8384254efba73261c271b71d3b075 src/CsoKit.Core/Formats/Psp/PspDiscIdentity.cs +10647b985a8eea66ff668748e148586e97006a3377b7d5f1fbc1bfc6d683d177 src/CsoKit.Core/Formats/Psp/PspParamSfoReader.cs +557a9eeb2d00117d8755a03713819c3544cf892c2e26ad1e42adf657a3c99b24 src/CsoKit.Core/Native/NativeCsoBackend.cs +a2b727b69c53b8c574b41affb323f2326812c72e712bdaa23cd15ceeadf7e507 src/CsoKit.Core/Native/NativeCsoCapabilities.cs +268ea9a05b8835282092151d3f60a4bac771db98c02438fbef70fccda3719857 src/CsoKit.Core/Native/NativeCsoRawCodec.cs +44b4b3184593571ad3ac7cc7dd02e1dfccc4b611dc6c920e3182d3d9d90d837e src/CsoKit.Core/Native/NativeCsoRuntime.cs +6ac402e6ff19b436121dae1857871319cfdd4a8e15fac888ad70f216648aba19 src/CsoKit.Core/Native/NativeCsoRuntimeInfo.cs +f1d9430e7fcf3b8d7b5e9fb17c5d151158cf58f6a5c6e013a754172aa3ce46e8 src/CsoKit.Core/Properties/AssemblyInfo.cs +7cbdd80a6693c9020c4a1320c99815e81e15b52da28fe2d789f7a9246e51f93a src/CsoKit.Core/Repair/RepairMode.cs +dbd53a726e7e507ec36a5866714d738288d10cc964930fe2d87889c5d5445d62 src/CsoKit.Core/Repair/RepairPlan.cs +7e98c5f21f8d58a50ce56b5083026b47be11b4baef761775e6a00af1a0775d88 src/CsoKit.Core/Repair/StreamingRepairService.cs +36039ae43b113d933e4afeee1bd456856e81beef1895dfefdf5b5ce9e87c7019 tests/CsoKit.App.Tests/CsoKit.App.Tests.csproj +471ebcda1c2b1689ab16a61edaa4f2286cbb2b1a0a11e46da889e0546fbf33a3 tests/CsoKit.App.Tests/OperationReportServiceTests.cs +5b4bad0f388b03886fb13cca7f5c0924bfe96d1477695d2b01525fd23c958457 tests/CsoKit.Tests/Application/CsoOperationFileNamePolicyTests.cs +5867be052449f5e281f71497d67f97c440428c8b7984930c87028798ad097324 tests/CsoKit.Tests/Application/CsoOperationResultTests.cs +043408ec1741516d1fa2c0cf9391f6572e992f2a37817d2315ef80fe1b6907da tests/CsoKit.Tests/Compression/CsoWorkerPolicyTests.cs +01600e6c4b8329114330374abd7e9a0cffd7860e18e545f4d803e7ebafdb18a0 tests/CsoKit.Tests/CsoKit.Tests.csproj +ca86647f4081372cb5fedd3ee3739c12bccd5e5e7b4f097949967d04d335e61c tests/CsoKit.Tests/DisableTestParallelization.cs +dfd64ca21cee7a987f1c0a4b9484f1a52ef70c4ddbde495773536aa540c64848 tests/CsoKit.Tests/Fixtures/ContainerFixtures.cs +47ca9293a7f2c1310817a3b04934be38e3a0594d4b9b7ad6c7efa91237340400 tests/CsoKit.Tests/Formats/CorruptContainerRefusalTests.cs +fb35e979ad8dae9fcad8e1371a4bda1acbcae625f6eb0fdd8191d27306d9006f tests/CsoKit.Tests/Formats/Cso/ContainerDeepVerifierTests.cs +fb3b6569fb422e32b059407b2c4e27298ff0e026e83b88fde4c4361905d31673 tests/CsoKit.Tests/Formats/Cso/CsoCliContractTests.cs +757a2bea714febfc40d6a0298ead8fa5a3832ac7068a49a3f4f55eb77aa65979 tests/CsoKit.Tests/Formats/Cso/CsoCompressJsonContractTests.cs +23a249fbd5cac8150890c8a17e0916b032a2aff53ea6ffadcbfe0bb3504c4cfb tests/CsoKit.Tests/Formats/Cso/CsoCompressionDecisionTests.cs +2a58dc3a35ccfcc0033acac35c9ddfed295f3aaa807eb459d74dbbb44867c411 tests/CsoKit.Tests/Formats/Cso/CsoCompressionProfilePolicyTests.cs +ce89dcc30b708660acdd2fcb848763489429e17f15cbed9dacd618b18b1da6d4 tests/CsoKit.Tests/Formats/Cso/CsoCompressorTests.cs +6dee7e8ec82045bae0c4dee7bde702f813f2df38df893fb9542c87e24af845c0 tests/CsoKit.Tests/Formats/Cso/CsoDecompressorCancellationTests.cs +737daf770a1dd62b49c97a581136c4966d5fcb33d98194d6d13c2d581238c1ed tests/CsoKit.Tests/Formats/Cso/CsoDecompressorTests.cs +7834130ab8b95e8e9ba615bec0f35b66478468341a84b71ad5ad5bac7e182666 tests/CsoKit.Tests/Formats/Cso/CsoDeepVerifierTests.cs +00881a7d6ce134b996272eaa600ef3733e1fd02c5fe62e9299b46baaa142eb7e tests/CsoKit.Tests/Formats/Cso/CsoDiskSpacePreflightTests.cs +13d11e679c9d6414fcc86648c71cb91f64956890ce9074f5891f848fd6e71b6d tests/CsoKit.Tests/Formats/Cso/CsoFileNamePolicyTests.cs +0c61a300b47d02a01d3a1cfea42688c9ad02e34dd29afbb6670a67463bfc52e2 tests/CsoKit.Tests/Formats/Cso/CsoHeaderReaderTests.cs +0fdf4a23ed531618a50f8b44375b069c84139f4c61025b12c11402f3ca5d7157 tests/CsoKit.Tests/Formats/Cso/CsoIndexReaderTests.cs +73a572cbcd9c3c44310984726500ea6f7636878affb5cda8b3bdc65db080f147 tests/CsoKit.Tests/Formats/Cso/CsoIndexShiftPolicyTests.cs +45f2ca31f4e39cf9de95e8159414ce6c75019b5b53d1a1584f716cd70862e44a tests/CsoKit.Tests/Formats/Cso/CsoMeasureEstimatorTests.cs +38e6d0022fb21de071f927cd9af3b7ae30e78c8c8f77f4923089869df2469e9e tests/CsoKit.Tests/Formats/Cso/CsoOutputPathPolicyTests.cs +8d1f8a6755989e794c30a03f8a0e16c6ce1eef3cf2d4c592bca89df813aaffd2 tests/CsoKit.Tests/Formats/Cso/CsoOutputSafetyPolicyTests.cs +145aac24824ade0f6dda03d0af1fc8ea8aa696120f1dd19d4b874b91583ff8ef tests/CsoKit.Tests/Formats/Cso/CsoRepairerTests.cs +9dd9c5838e99786a594a842f4d402e33c7913da746932773f0ac7cfd6405f436 tests/CsoKit.Tests/Formats/Cso/CsoSectorEngineFoundationTests.cs +52959792636d55a5f73f7acf2ccc51f3a6dd256ddd432335bb35b0c27ec079cc tests/CsoKit.Tests/Formats/Cso/CsoTestFileFactory.cs +58e1c239b4a8ec88771eed592c11895ba24eeef7d987ce6317f8010e74b5db49 tests/CsoKit.Tests/Formats/Cso/CsoTrialEngineTests.cs +7e16af7a03dfe8fd7a48cd4f510d510b373ccf144b8edde4314ab4c1dfc9ca15 tests/CsoKit.Tests/Formats/Cso/CsoTrialPlannerTests.cs +81e918e4aa3d91b9406924bb807f39e916f45f40d264d86acf8c03a17c7e7cd2 tests/CsoKit.Tests/Formats/Cso/CsoVerifierTests.cs +7cf886e0db62b65f8fa5f35b3de45c36888da1758430508416613be821a4ab64 tests/CsoKit.Tests/Formats/Cso/DeepVerificationCancellationTests.cs +21a156c9493835f6f38d504e1d9c19933eeefb7e7591163f9c21435f3dcdd44d tests/CsoKit.Tests/Formats/DiscImage/FormatDetectorTests.cs +bf4d9e90e6dcefc3378d22f120503827f54fd562c69d370b7d14179aea5d3662 tests/CsoKit.Tests/Formats/GoldenContainerTests.cs +7e2a87d0277ac7ab06f315fad1669121146c51f95f0a7c041aa27dc7b63ebdac tests/CsoKit.Tests/Formats/Iso/IsoAlignmentPolicyTests.cs +14be7a5250869cd68c5df30118a27335b76f484904a347b14a4939688417a307 tests/CsoKit.Tests/Formats/Iso/PspIsoValidatorTests.cs +df0137f94380f984dda8ae147efc6f0c48eed2b20613baae07009991d7bcc392 tests/CsoKit.Tests/Formats/PspIsoFixtureTests.cs +62d097d1d212ff8e1497a8685a851887640a2cedf771db345d08923dafa6a604 tests/CsoKit.Tests/Formats/RepairGoldenFixtureTests.cs +8bf025bed192f5d81767aa91d591b1ec5f2c27ae617ecaacabf37f7c9c2d759b tests/CsoKit.Tests/Native/NativeCsoRuntimeTests.cs +ba99b4ca112cd18d2dba3ed8d63d80a51a780362745f41e6651f87c458350e0b tests/CsoKit.Tests/Native/NativeLibrarySearchPolicyTests.cs diff --git a/SOURCE_FILES.txt b/SOURCE_FILES.txt new file mode 100644 index 0000000..d1e02e0 --- /dev/null +++ b/SOURCE_FILES.txt @@ -0,0 +1,259 @@ +.gitattributes +.github/workflows/ci.yml +.github/workflows/release.yml +.gitignore +CHANGES.md +CONTRIBUTING.md +CsoKit.slnx +Directory.Build.props +LICENSE.txt +README.md +RELEASE_NOTES.md +THIRD_PARTY_NOTICES.md +VERSION +docs/CLI.md +docs/HARDENING_IMPLEMENTATION_REPORT.md +docs/NATIVE_BUILD.md +docs/README.md +docs/SECURITY_HARDENING.md +docs/archive/CHANGELOG_FIX_NOTES.md +docs/archive/R1_ARCHITECTURE_REPAIR.md +docs/archive/R3C_RELEASE_HARDENING.md +docs/archive/R3D_BENCHMARK_TRUTH.md +docs/archive/R3E_REAL_CORPUS_EVIDENCE.md +docs/archive/RELEASE_0_5_0_SCORECARD.md +docs/archive/RELEASE_SCORECARD.md +docs/release/RELEASE_0_6_0_GATE.md +native/CsoKit.Native/CMakeLists.txt +native/CsoKit.Native/include/csokit_native.h +native/CsoKit.Native/include/csokit_version.h.in +native/CsoKit.Native/src/csokit_native.cpp +native/third_party/zopfli/COPYING +native/third_party/zopfli/README +native/third_party/zopfli/src/zopfli/blocksplitter.c +native/third_party/zopfli/src/zopfli/blocksplitter.h +native/third_party/zopfli/src/zopfli/cache.c +native/third_party/zopfli/src/zopfli/cache.h +native/third_party/zopfli/src/zopfli/deflate.c +native/third_party/zopfli/src/zopfli/deflate.h +native/third_party/zopfli/src/zopfli/gzip_container.c +native/third_party/zopfli/src/zopfli/gzip_container.h +native/third_party/zopfli/src/zopfli/hash.c +native/third_party/zopfli/src/zopfli/hash.h +native/third_party/zopfli/src/zopfli/katajainen.c +native/third_party/zopfli/src/zopfli/katajainen.h +native/third_party/zopfli/src/zopfli/lz77.c +native/third_party/zopfli/src/zopfli/lz77.h +native/third_party/zopfli/src/zopfli/squeeze.c +native/third_party/zopfli/src/zopfli/squeeze.h +native/third_party/zopfli/src/zopfli/symbols.h +native/third_party/zopfli/src/zopfli/tree.c +native/third_party/zopfli/src/zopfli/tree.h +native/third_party/zopfli/src/zopfli/util.c +native/third_party/zopfli/src/zopfli/util.h +native/third_party/zopfli/src/zopfli/zlib_container.c +native/third_party/zopfli/src/zopfli/zlib_container.h +native/third_party/zopfli/src/zopfli/zopfli.h +native/third_party/zopfli/src/zopfli/zopfli_bin.c +native/third_party/zopfli/src/zopfli/zopfli_lib.c +scripts/Build-Native.ps1 +scripts/OutputFileNamePolicy.ps1 +scripts/Publish-Release.ps1 +scripts/Publish-SourcePackage.ps1 +scripts/Remove-Utf8Bom.ps1 +scripts/Run-BenchmarkTruthLayer.ps1 +scripts/Run-FinalReleaseGate.ps1 +scripts/Run-OfficialReleaseGate.ps1 +scripts/Run-ProfileRoundtripMatrix.ps1 +scripts/Run-PublishedExeSmoke.ps1 +scripts/Run-RealLocalCorpusGate.ps1 +scripts/Run-ReleaseGate.ps1 +scripts/Run-RoundtripGate.ps1 +scripts/Test-RepoTextEncoding.ps1 +scripts/Verify-Hardening.ps1 +scripts/Verify-Release.ps1 +src/CsoKit.App/App.xaml +src/CsoKit.App/App.xaml.cs +src/CsoKit.App/Assets/Icons/advanced_key.png +src/CsoKit.App/Assets/Icons/csokit.ico +src/CsoKit.App/Assets/Icons/csokit_32.png +src/CsoKit.App/Assets/Icons/status_error.png +src/CsoKit.App/Assets/Icons/status_success.png +src/CsoKit.App/CsoKit.App.csproj +src/CsoKit.App/Localization/ArabicUiText.cs +src/CsoKit.App/MainWindow.xaml +src/CsoKit.App/MainWindow.xaml.cs +src/CsoKit.App/Models/UiLogEntry.cs +src/CsoKit.App/Models/UiOperationKind.cs +src/CsoKit.App/Models/UiTaskItem.cs +src/CsoKit.App/Properties/AssemblyInfo.cs +src/CsoKit.App/Services/OperationReportService.cs +src/CsoKit.App/ViewModels/MainWindowViewModel.Operations.cs +src/CsoKit.App/ViewModels/MainWindowViewModel.cs +src/CsoKit.App/ViewModels/OperationSummaryViewModel.cs +src/CsoKit.Application/CsoKit.Application.csproj +src/CsoKit.Application/CsoOperationData.cs +src/CsoKit.Application/CsoOperationDetail.cs +src/CsoKit.Application/CsoOperationDetailsBuilder.cs +src/CsoKit.Application/CsoOperationResult.cs +src/CsoKit.Application/CsoOperationService.Verification.cs +src/CsoKit.Application/CsoOperationService.cs +src/CsoKit.Cli/CliExitCodes.cs +src/CsoKit.Cli/Commands/AnalyzeCommand.cs +src/CsoKit.Cli/Commands/CodecsCommand.cs +src/CsoKit.Cli/Commands/CompressCommand.cs +src/CsoKit.Cli/Commands/CsoCommandDispatcher.cs +src/CsoKit.Cli/Commands/CsoCommandError.cs +src/CsoKit.Cli/Commands/CsoCompressJsonContract.cs +src/CsoKit.Cli/Commands/CsoProfileOutput.cs +src/CsoKit.Cli/Commands/DecompressCommand.cs +src/CsoKit.Cli/Commands/DetectCommand.cs +src/CsoKit.Cli/Commands/InfoCommand.cs +src/CsoKit.Cli/Commands/JsonConsole.cs +src/CsoKit.Cli/Commands/NativeInfoCommand.cs +src/CsoKit.Cli/Commands/RepairCommand.cs +src/CsoKit.Cli/Commands/VerifyCommand.cs +src/CsoKit.Cli/CsoKit.Cli.csproj +src/CsoKit.Cli/Program.cs +src/CsoKit.Core/Analysis/PspIsoAnalysisResult.cs +src/CsoKit.Core/Compression/CsoWorkerPolicy.cs +src/CsoKit.Core/Compression/Trials/CodecTrialCandidateResult.cs +src/CsoKit.Core/Compression/Trials/CodecTrialDecisionMetrics.cs +src/CsoKit.Core/Compression/Trials/CodecTrialReport.cs +src/CsoKit.Core/Compression/Trials/CodecTrialSummary.cs +src/CsoKit.Core/Compression/Trials/CodecTrialSummaryBuilder.cs +src/CsoKit.Core/CsoKit.Core.csproj +src/CsoKit.Core/Formats/Containers/BlockContainerReadException.cs +src/CsoKit.Core/Formats/Containers/BlockContainerReaderFactory.cs +src/CsoKit.Core/Formats/Containers/ContainerDeepVerifier.cs +src/CsoKit.Core/Formats/Containers/Cso1ContainerReader.cs +src/CsoKit.Core/Formats/Containers/Cso2ContainerReader.cs +src/CsoKit.Core/Formats/Containers/CsoLikeContainerReader.cs +src/CsoKit.Core/Formats/Containers/CsoLikeHeaderReader.cs +src/CsoKit.Core/Formats/Containers/DaxContainerReader.cs +src/CsoKit.Core/Formats/Containers/IBlockContainerReader.cs +src/CsoKit.Core/Formats/Containers/IsoContainerReader.cs +src/CsoKit.Core/Formats/Containers/Lz4BlockDecoder.cs +src/CsoKit.Core/Formats/Containers/ZsoContainerReader.cs +src/CsoKit.Core/Formats/Cso/Codecs/CsoCodecKind.cs +src/CsoKit.Core/Formats/Cso/Codecs/CsoCodecTrial.cs +src/CsoKit.Core/Formats/Cso/Codecs/CsoCodecTrialResult.cs +src/CsoKit.Core/Formats/Cso/Codecs/CsoTrialEngine.cs +src/CsoKit.Core/Formats/Cso/Codecs/CsoTrialPlan.cs +src/CsoKit.Core/Formats/Cso/Codecs/CsoTrialPlanner.cs +src/CsoKit.Core/Formats/Cso/Codecs/ICsoCodecTrial.cs +src/CsoKit.Core/Formats/Cso/Codecs/Managed/ManagedDeflateTrial.cs +src/CsoKit.Core/Formats/Cso/Codecs/Native/NativeLibDeflateTrial.cs +src/CsoKit.Core/Formats/Cso/Codecs/Native/NativeUnavailableTrial.cs +src/CsoKit.Core/Formats/Cso/Codecs/Native/NativeZlibTrial.cs +src/CsoKit.Core/Formats/Cso/Codecs/Native/NativeZopfliTrial.cs +src/CsoKit.Core/Formats/Cso/CompressionMethod.cs +src/CsoKit.Core/Formats/Cso/Cso1Writer.cs +src/CsoKit.Core/Formats/Cso/CsoBestCandidateSelector.cs +src/CsoKit.Core/Formats/Cso/CsoBlockReader.cs +src/CsoKit.Core/Formats/Cso/CsoCompressOptions.cs +src/CsoKit.Core/Formats/Cso/CsoCompressProgress.cs +src/CsoKit.Core/Formats/Cso/CsoCompressResult.cs +src/CsoKit.Core/Formats/Cso/CsoCompressionProfile.cs +src/CsoKit.Core/Formats/Cso/CsoCompressionProfilePolicy.cs +src/CsoKit.Core/Formats/Cso/CsoCompressionProfileSettings.cs +src/CsoKit.Core/Formats/Cso/CsoCompressionWorker.cs +src/CsoKit.Core/Formats/Cso/CsoCompressor.cs +src/CsoKit.Core/Formats/Cso/CsoConstants.cs +src/CsoKit.Core/Formats/Cso/CsoDecompressOptions.cs +src/CsoKit.Core/Formats/Cso/CsoDecompressProgress.cs +src/CsoKit.Core/Formats/Cso/CsoDecompressResult.cs +src/CsoKit.Core/Formats/Cso/CsoDecompressor.cs +src/CsoKit.Core/Formats/Cso/CsoDeepVerifier.cs +src/CsoKit.Core/Formats/Cso/CsoDeepVerifyIssue.cs +src/CsoKit.Core/Formats/Cso/CsoDeepVerifyResult.cs +src/CsoKit.Core/Formats/Cso/CsoDiskSpacePreflight.cs +src/CsoKit.Core/Formats/Cso/CsoDiskSpacePreflightResult.cs +src/CsoKit.Core/Formats/Cso/CsoFileNamePolicy.cs +src/CsoKit.Core/Formats/Cso/CsoHeader.cs +src/CsoKit.Core/Formats/Cso/CsoHeaderReadResult.cs +src/CsoKit.Core/Formats/Cso/CsoHeaderReader.cs +src/CsoKit.Core/Formats/Cso/CsoIndexBuilder.cs +src/CsoKit.Core/Formats/Cso/CsoIndexEntry.cs +src/CsoKit.Core/Formats/Cso/CsoIndexReadResult.cs +src/CsoKit.Core/Formats/Cso/CsoIndexReader.cs +src/CsoKit.Core/Formats/Cso/CsoIndexShiftPolicy.cs +src/CsoKit.Core/Formats/Cso/CsoMeasureEstimator.cs +src/CsoKit.Core/Formats/Cso/CsoMeasureOptions.cs +src/CsoKit.Core/Formats/Cso/CsoMeasureResult.cs +src/CsoKit.Core/Formats/Cso/CsoOrderedOutputWriter.cs +src/CsoKit.Core/Formats/Cso/CsoOutputPathPolicy.cs +src/CsoKit.Core/Formats/Cso/CsoOutputSafetyPolicy.cs +src/CsoKit.Core/Formats/Cso/CsoOutputSafetyResult.cs +src/CsoKit.Core/Formats/Cso/CsoRepairMode.cs +src/CsoKit.Core/Formats/Cso/CsoRepairOptions.cs +src/CsoKit.Core/Formats/Cso/CsoRepairResult.cs +src/CsoKit.Core/Formats/Cso/CsoRepairer.cs +src/CsoKit.Core/Formats/Cso/CsoVerificationIssue.cs +src/CsoKit.Core/Formats/Cso/CsoVerificationResult.cs +src/CsoKit.Core/Formats/Cso/CsoVerifier.cs +src/CsoKit.Core/Formats/Cso/RawDeflateVerifier.cs +src/CsoKit.Core/Formats/Cso/SectorJob.cs +src/CsoKit.Core/Formats/Cso/SectorResult.cs +src/CsoKit.Core/Formats/DiscImage/DetectedDiscFormat.cs +src/CsoKit.Core/Formats/DiscImage/FormatDetectionResult.cs +src/CsoKit.Core/Formats/DiscImage/FormatDetector.cs +src/CsoKit.Core/Formats/Iso/Iso9660Entry.cs +src/CsoKit.Core/Formats/Iso/Iso9660Reader.cs +src/CsoKit.Core/Formats/Iso/IsoAlignmentPolicy.cs +src/CsoKit.Core/Formats/Iso/IsoAlignmentResult.cs +src/CsoKit.Core/Formats/Iso/PspIsoValidationIssue.cs +src/CsoKit.Core/Formats/Iso/PspIsoValidationResult.cs +src/CsoKit.Core/Formats/Iso/PspIsoValidator.cs +src/CsoKit.Core/Formats/Psp/PspDiscIdentity.cs +src/CsoKit.Core/Formats/Psp/PspParamSfoReader.cs +src/CsoKit.Core/Native/NativeCsoBackend.cs +src/CsoKit.Core/Native/NativeCsoCapabilities.cs +src/CsoKit.Core/Native/NativeCsoRawCodec.cs +src/CsoKit.Core/Native/NativeCsoRuntime.cs +src/CsoKit.Core/Native/NativeCsoRuntimeInfo.cs +src/CsoKit.Core/Properties/AssemblyInfo.cs +src/CsoKit.Core/Repair/RepairMode.cs +src/CsoKit.Core/Repair/RepairPlan.cs +src/CsoKit.Core/Repair/StreamingRepairService.cs +tests/CsoKit.App.Tests/CsoKit.App.Tests.csproj +tests/CsoKit.App.Tests/OperationReportServiceTests.cs +tests/CsoKit.Tests/Application/CsoOperationFileNamePolicyTests.cs +tests/CsoKit.Tests/Application/CsoOperationResultTests.cs +tests/CsoKit.Tests/Compression/CsoWorkerPolicyTests.cs +tests/CsoKit.Tests/CsoKit.Tests.csproj +tests/CsoKit.Tests/DisableTestParallelization.cs +tests/CsoKit.Tests/Fixtures/ContainerFixtures.cs +tests/CsoKit.Tests/Formats/CorruptContainerRefusalTests.cs +tests/CsoKit.Tests/Formats/Cso/ContainerDeepVerifierTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoCliContractTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoCompressJsonContractTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoCompressionDecisionTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoCompressionProfilePolicyTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoCompressorTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoDecompressorCancellationTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoDecompressorTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoDeepVerifierTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoDiskSpacePreflightTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoFileNamePolicyTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoHeaderReaderTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoIndexReaderTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoIndexShiftPolicyTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoMeasureEstimatorTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoOutputPathPolicyTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoOutputSafetyPolicyTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoRepairerTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoSectorEngineFoundationTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoTestFileFactory.cs +tests/CsoKit.Tests/Formats/Cso/CsoTrialEngineTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoTrialPlannerTests.cs +tests/CsoKit.Tests/Formats/Cso/CsoVerifierTests.cs +tests/CsoKit.Tests/Formats/Cso/DeepVerificationCancellationTests.cs +tests/CsoKit.Tests/Formats/DiscImage/FormatDetectorTests.cs +tests/CsoKit.Tests/Formats/GoldenContainerTests.cs +tests/CsoKit.Tests/Formats/Iso/IsoAlignmentPolicyTests.cs +tests/CsoKit.Tests/Formats/Iso/PspIsoValidatorTests.cs +tests/CsoKit.Tests/Formats/PspIsoFixtureTests.cs +tests/CsoKit.Tests/Formats/RepairGoldenFixtureTests.cs +tests/CsoKit.Tests/Native/NativeCsoRuntimeTests.cs +tests/CsoKit.Tests/Native/NativeLibrarySearchPolicyTests.cs diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 61663c7..15fb053 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -1,6 +1,6 @@ # Third-Party Notices -Hakamiq CsoKit uses a few third-party compression libraries in the native backend. +CsoKit uses a few third-party compression libraries in the native backend. These components are not owned by HAKAMIQ. Each one stays under its original license. @@ -11,7 +11,7 @@ These components are not owned by HAKAMIQ. Each one stays under its original lic - Native build version: v1.3.2 - License: zlib License -Hakamiq CsoKit uses zlib for raw-Deflate candidate trials, including default, filtered, Huffman-only, and RLE strategies. +CsoKit uses zlib for raw-Deflate candidate trials, including default, filtered, Huffman-only, and RLE strategies. ## libdeflate @@ -20,7 +20,7 @@ Hakamiq CsoKit uses zlib for raw-Deflate candidate trials, including default, fi - Native build version: v1.25 - License: MIT License -Hakamiq CsoKit uses libdeflate for raw-Deflate candidate trials at several compression levels. +CsoKit uses libdeflate for raw-Deflate candidate trials at several compression levels. ## Zopfli @@ -36,4 +36,4 @@ Zopfli is only used when `--zopfli` is explicitly requested. Normal compression The managed Deflate path remains available without the native backend. -See LICENSE.txt for Hakamiq CsoKit license terms. \ No newline at end of file +See LICENSE.txt for CsoKit license terms. \ No newline at end of file diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..a918a2a --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.6.0 diff --git a/docs/CLI.md b/docs/CLI.md index 3fa981e..cb761a0 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -1,6 +1,6 @@ -# Hakamiq CsoKit CLI Reference +# CsoKit CLI Reference -This is the command-line reference for `hakamiq-cso.exe`. +This is the command-line reference for `csokit.exe`. The desktop app is the easier path for normal use. The CLI is for scripting, automation, diagnostics, and cases where you want exact control over compression, repair, or verification. @@ -8,33 +8,33 @@ The desktop app is the easier path for normal use. The CLI is for scripting, aut Print help: - .\hakamiq-cso.exe --help + .\csokit.exe --help Check the installed version: - .\hakamiq-cso.exe --version + .\csokit.exe --version Check whether the native backend is available: - .\hakamiq-cso.exe native-info + .\csokit.exe native-info List available codecs: - .\hakamiq-cso.exe codecs + .\csokit.exe codecs ## Inspect a file Show CSO metadata: - .\hakamiq-cso.exe info ".\game.cso" + .\csokit.exe info ".\game.cso" Detect the input format before doing anything else: - .\hakamiq-cso.exe detect ".\game.iso" + .\csokit.exe detect ".\game.iso" JSON is useful when another script needs to read the result: - .\hakamiq-cso.exe detect ".\game.cso" --json + .\csokit.exe detect ".\game.cso" --json Detected formats include ISO, CSO1, CSO2, ZSO, DAX, and unknown input. @@ -42,11 +42,11 @@ Detected formats include ISO, CSO1, CSO2, ZSO, DAX, and unknown input. Analyze checks PSP ISO structure without changing the file. - .\hakamiq-cso.exe analyze ".\game.iso" --psp + .\csokit.exe analyze ".\game.iso" --psp For scripts: - .\hakamiq-cso.exe analyze ".\game.iso" --psp --json + .\csokit.exe analyze ".\game.iso" --psp --json Run this before compression if you want a quick sanity check. @@ -54,41 +54,41 @@ Run this before compression if you want a quick sanity check. Basic verification checks the container structure: - .\hakamiq-cso.exe verify ".\game.cso" + .\csokit.exe verify ".\game.cso" Deep verification reads compressed blocks and validates more of the file: - .\hakamiq-cso.exe verify ".\game.cso" --deep + .\csokit.exe verify ".\game.cso" --deep Add SHA256 when you need a stable hash for records or comparison: - .\hakamiq-cso.exe verify ".\game.cso" --deep --sha256 + .\csokit.exe verify ".\game.cso" --deep --sha256 Machine-readable result: - .\hakamiq-cso.exe verify ".\game.cso" --deep --sha256 --json + .\csokit.exe verify ".\game.cso" --deep --sha256 --json ## Compress ISO to CSO Default compression writes a CSO next to the ISO: - .\hakamiq-cso.exe compress ".\game.iso" + .\csokit.exe compress ".\game.iso" Set the output path when you need a specific name: - .\hakamiq-cso.exe compress ".\game.iso" -o ".\game.cso" + .\csokit.exe compress ".\game.iso" -o ".\game.cso" Overwrite only when you mean it: - .\hakamiq-cso.exe compress ".\game.iso" -o ".\game.cso" --force + .\csokit.exe compress ".\game.iso" -o ".\game.cso" --force Estimate output size without writing a CSO: - .\hakamiq-cso.exe compress ".\game.iso" --measure + .\csokit.exe compress ".\game.iso" --measure For automation: - .\hakamiq-cso.exe compress ".\game.iso" --profile fast --json + .\csokit.exe compress ".\game.iso" --profile fast --json ## Profiles @@ -110,11 +110,11 @@ Available profiles: Pick a profile: - .\hakamiq-cso.exe compress ".\game.iso" --profile fast + .\csokit.exe compress ".\game.iso" --profile fast Shortcut: - .\hakamiq-cso.exe compress ".\game.iso" --fast + .\csokit.exe compress ".\game.iso" --fast Do not combine `--fast` with another explicit profile. Pick one. @@ -122,19 +122,19 @@ Do not combine `--fast` with another explicit profile. Pick one. Threads: - .\hakamiq-cso.exe compress ".\game.iso" --threads 8 + .\csokit.exe compress ".\game.iso" --threads 8 Block size: - .\hakamiq-cso.exe compress ".\game.iso" --block 16K + .\csokit.exe compress ".\game.iso" --block 16K Optional Zopfli trials: - .\hakamiq-cso.exe compress ".\game.iso" --zopfli + .\csokit.exe compress ".\game.iso" --zopfli Codec winner report: - .\hakamiq-cso.exe compress ".\game.iso" --codec-report + .\csokit.exe compress ".\game.iso" --codec-report Block size accepts raw bytes, `K`, or `M`. It must be at least 2048 and a power of two. Larger blocks can improve compression, but they may hurt compatibility or random-read behavior. For PSP safety, 2048 is still the sensible default. @@ -142,21 +142,21 @@ Block size accepts raw bytes, `K`, or `M`. It must be at least 2048 and a power Default output goes next to the CSO: - .\hakamiq-cso.exe decompress ".\game.cso" + .\csokit.exe decompress ".\game.cso" Choose an output path: - .\hakamiq-cso.exe decompress ".\game.cso" -o ".\game.iso" + .\csokit.exe decompress ".\game.cso" -o ".\game.iso" Overwrite intentionally: - .\hakamiq-cso.exe decompress ".\game.cso" -o ".\game.iso" --force + .\csokit.exe decompress ".\game.cso" -o ".\game.iso" --force ## Repair and normalize Repair is conservative. It rebuilds readable input into game-safe CSO1, but it does not invent missing data. - .\hakamiq-cso.exe repair ".\game.cso" -o ".\fixed.cso" --profile game-safe --deep-verify + .\csokit.exe repair ".\game.cso" -o ".\fixed.cso" --profile game-safe --deep-verify Readable input can include ISO, CSO1, ZSO, DAX, and supported CSO2. Output is CSO1 by default. @@ -166,19 +166,19 @@ Padding a non-2048-aligned ISO only happens when explicit repair behavior is req ## Output naming -If the default output already exists, Hakamiq CsoKit chooses a safe converted name: +The output base name must contain 2 to 10 characters; the extension is not counted. If the default output already exists, CsoKit uses a short numbered suffix while preserving the limit: game.cso - game - Hakamiq Converted.cso - game - Hakamiq Converted 2.cso + game-2.cso + game-3.cso -With `-o`, the destination folder must already exist. +Long automatic names are shortened to ten characters, and one-character names are padded to two characters. With `-o`, the destination folder must already exist and the same length rule applies. ## Native backend Release packages include: - Hakamiq.Cso.Native.dll + CsoKit.Native.dll Keep it next to the executables. @@ -186,7 +186,7 @@ The native backend adds zlib and libdeflate raw-Deflate candidates. Managed Defl Quick check: - .\hakamiq-cso.exe native-info + .\csokit.exe native-info ## JSON output @@ -194,9 +194,9 @@ Add `--json` when another program needs structured output. Examples: - .\hakamiq-cso.exe verify ".\game.cso" --json - .\hakamiq-cso.exe verify ".\game.cso" --deep --sha256 --json - .\hakamiq-cso.exe compress ".\game.iso" --measure --profile smallest --json + .\csokit.exe verify ".\game.cso" --json + .\csokit.exe verify ".\game.cso" --deep --sha256 --json + .\csokit.exe compress ".\game.iso" --measure --profile smallest --json Compression and measure JSON include `schemaVersion`, `command`, `mode`, `success`, `options`, `metrics`, and `error` when the command fails. diff --git a/docs/HARDENING_IMPLEMENTATION_REPORT.md b/docs/HARDENING_IMPLEMENTATION_REPORT.md new file mode 100644 index 0000000..1fa4750 --- /dev/null +++ b/docs/HARDENING_IMPLEMENTATION_REPORT.md @@ -0,0 +1,145 @@ +# CsoKit hardening implementation report + +Date: 2026-08-02 +Version source: `VERSION` (`0.6.0`) + +## Scope + +This change set addresses the security and architecture findings covering native DLL loading, cancellation, compression worker bounds, ABI enforcement, native integration tests, application-layer boundaries, WPF decomposition, and centralized versioning. + +## Implemented changes + +### Native boundary + +- Production native resolution is restricted to `AppContext.BaseDirectory`. +- Ancestor and `artifacts` probing requires the explicit `CSOKIT_NATIVE_DEV_SEARCH=1` development switch. +- Failure to find an approved library is fail-closed and does not fall back to the platform DLL search path. +- Optional SHA-256 enforcement is available through `CSOKIT_NATIVE_SHA256`. +- Managed/native ABI compatibility is fixed at ABI 2 and validated before every codec path can become available. + +### Cancellation and final output promotion + +- Cancellation tokens now flow through container deep verification, CSO deep verification, repair, CLI repair, CLI deep verify, and WPF operations. +- Block loops check cancellation between blocks. +- Compression and CSO writing check cancellation immediately before final `File.Move` promotion. +- WPF now exposes an active Stop button while an operation is running. +- `repair` and deep `verify` handle Ctrl+C and return exit code 130. + +### Compression resource policy + +- `CsoWorkerPolicy` centralizes default, configured, and absolute worker limits. +- The hard ceiling is 64 workers; the operational ceiling is processor-scaled or reduced with `CSOKIT_MAX_WORKERS`. +- Core, CLI, and WPF use the same validation. +- Queue capacity uses checked bounded arithmetic. + +### Native CI and published-artifact validation + +- CI builds the native backend before managed tests. +- Native integration tests fail when the DLL or mandatory capabilities are missing. +- Tests exercise zlib, libdeflate, and Zopfli raw-deflate/inflate round trips. +- Release publishing stages the actual DLL beside the published executable and performs a real published CLI ISO → CSO → ISO SHA-256 round trip. + +### Application boundary and WPF decomposition + +- Added `CsoKit.Application` as the use-case boundary between CLI/WPF and Core. +- Centralized container reader creation in `BlockContainerReaderFactory`. +- CLI no longer references `CsoKit.Core` as a project and no longer instantiates compressor, repair, shallow verifier, or deep verifier implementations directly. +- Application results expose typed paths, format, byte metrics, error code, operation DTOs, and structured detail records. +- Typed detail records are now the source of rendered `Details`; the former free-text detail parser was removed. +- WPF no longer parses English result text to recover sizes, savings, or report structure. +- Operation report writing was extracted from the ViewModel. +- MainWindowViewModel operation execution was split into a separate partial file. +- Added a Windows test project for report rendering outside a live WPF window. + +### Version source + +- Added root `VERSION` and `Directory.Build.props`. +- .NET projects read one managed version source. +- CMake reads the same file and generates native version/ABI macros. +- Publish and verification scripts default to the root version instead of duplicated literals. + +## Tests added or strengthened + +- Worker policy minimum, maximum, environment override, and compressor rejection. +- Deep verification cancellation before input and between blocks. +- Production native search policy. +- Mandatory native ABI/capability checks. +- zlib/libdeflate/Zopfli native round trips. +- Typed operation result rendering without reverse-parsing free text. +- Arabic WPF report rendering from structured operation details. + +There are 150 `[Fact]`/`[Theory]` declarations in the source tree after this change. Runtime case counts can be higher because theories expand into multiple cases. + +## Validation performed in the editing environment + +- XML/XAML/CSProj/Solution parsing: PASS. +- GitHub Actions YAML parsing: PASS. +- C# delimiter and lexical structural scan across 168 files: PASS. +- Project and solution reference existence: PASS. +- WPF event handler linkage scan: PASS. +- Stale WPF service symbol scan: PASS. +- Dependency direction scan: PASS. +- `git diff --check`: PASS. +- UI direction attributes: unchanged. + +## Follow-up correction after external build review + +- Fixed `CS0165` in CLI thread parsing by separating integer parsing from worker-policy validation. +- Fixed the WPF namespace collision by deriving `App` explicitly from `System.Windows.Application`. +- Removed the CLI project reference to Core and routed long-running/state-changing commands through Application DTOs. +- Removed `CsoOperationDetailParser`; structured detail records now generate the compatibility text view. +- Added architecture source guards to `Verify-Hardening.ps1`. + + +## Follow-up correction after v2 Windows build review + +- Added the explicit `System.IO` imports required by the WPF report and operation partial files. +- Added the explicit `CsoKit.App.Localization` import required by the split ViewModel partial. +- Separated WPF worker-count parsing from policy validation to eliminate the same definite-assignment failure already fixed in CLI. +- Changed native round-trip fixtures to use deliberately compressible data for every zlib strategy. +- Added a separate native integration theory proving that expansion-prone Huffman-only and RLE candidates are rejected cleanly when the native layer reports `OUTPUT_TOO_SMALL`, with no partial output exposed. + +## Follow-up correction after v4 Windows CLI review + +- Reordered `compress`, `decompress`, and `repair` handling so early validation failures are processed before typed operation data is required. +- Successful operations still require their typed DTO and fail as an internal contract error if it is missing. +- JSON output now preserves the common failure envelope when operation data is absent; command metrics are serialized as `null`. +- Changed the general JSON failure test to use a valid short output name so it continues testing the intended missing-input path. +- Added text and JSON boundary coverage for one-character and eleven-character output names across all three state-changing commands. +- Replaced the repair suffix assertion with `Assert.EndsWith`. + +## Runtime validation limitation + +The editing environment did not contain the .NET SDK or PowerShell and could not download them. Managed builds, WPF compilation, native Windows compilation, and the runtime test suite were therefore not executed independently here. + +Run the following on Windows before merge or release: + +```powershell +.\scripts\Verify-Hardening.ps1 -Configuration Release +``` + +The script performs restore, native build, Debug/Release managed builds, native-backed tests, release publishing, and release verification. + +## Commit suggestion + +`fix(security): harden native loading, cancellation, and application boundaries` +## Output file-name length policy + +- Output base names are validated at the Application boundary and must contain 2 to 10 user-visible characters; the extension is not counted. +- Automatic compression/decompression names are normalized into that range. +- Repair suggestions use a short `-r` suffix and numbered collision suffixes remain within ten characters. +- Input file names are not restricted, so existing game images with long names remain usable. +- Unicode text elements are counted instead of raw UTF-16 code units. + + +## Release-script filename-policy hardening + +The release gates now create artifacts in isolated work directories and use short fixed filenames. `scripts/OutputFileNamePolicy.ps1` counts Unicode text elements using `System.Globalization.StringInfo`, matching the Core filename policy. The main hardening gate verifies that all release scripts load and invoke this guard, and checks literal `.cso`/`.iso` names for the 2–10 rule. + + +## v7 published executable smoke integration + +- Updated the exact help contract expected by `Run-PublishedExeSmoke.ps1` to include CSO, ZSO, and DAX verification inputs. +- The smoke gate now builds the Release native backend and copies `CsoKit.Native.dll` beside the published CLI before `native-info`. +- `Verify-Hardening.ps1` now executes the standalone smoke with real-ISO gates skipped; full real-profile roundtrips remain available through the dedicated invocation. +- Source guards require the current help contract, native build/staging, and main-gate integration. diff --git a/docs/NATIVE_BUILD.md b/docs/NATIVE_BUILD.md index b13e4cd..fcc215c 100644 --- a/docs/NATIVE_BUILD.md +++ b/docs/NATIVE_BUILD.md @@ -1,6 +1,6 @@ # Native Build Notes -Hakamiq CsoKit does not require the native backend to function. +CsoKit does not require the native backend to function. The managed path stays available for detect, analyze, verify, repair, decompress, and compress. Native code only adds extra raw-Deflate candidates such as zlib, libdeflate, and optional Zopfli. @@ -14,7 +14,7 @@ Run this when you want the full release layout or when you are testing native co Then check what the CLI can actually see: - .\hakamiq-cso.exe native-info + .\csokit.exe native-info The report should be honest about zlib, libdeflate, Zopfli, and anything unavailable. @@ -28,21 +28,31 @@ If that fails because the machine is offline, do not patch around it by hardcodi This is enough for normal .NET validation when native dependencies are not available: - dotnet build Hakamiq.CsoKit.slnx --no-restore - dotnet test Hakamiq.CsoKit.slnx --no-build --no-restore - .\hakamiq-cso.exe native-info + dotnet build CsoKit.slnx --no-restore + dotnet test CsoKit.slnx --no-build --no-restore + .\csokit.exe native-info -Managed Deflate, container decoding, PSP ISO analysis, JSON diagnostics, and repair safety should still work without Hakamiq.Cso.Native.dll. +Managed Deflate, container decoding, PSP ISO analysis, JSON diagnostics, and repair safety should still work without CsoKit.Native.dll. ## Release expectation Release packages should include: - Hakamiq.Cso.Native.dll + CsoKit.Native.dll Keep it next to: - hakamiq-cso.exe - Hakamiq.Cso.App.exe + csokit.exe + CsoKit.App.exe -If native-info says unavailable in a release package, check the published ZIP layout first. Most native problems are packaging problems, not compression bugs. \ No newline at end of file +If native-info says unavailable in a release package, check the published ZIP layout first. Most native problems are packaging problems, not compression bugs. +## Runtime loading policy + +Release builds must place `CsoKit.Native.dll` beside the executable. Production never +searches the current directory or repository `artifacts` paths. Repository probing is a +developer-only opt-in through `CSOKIT_NATIVE_DEV_SEARCH=1`; optionally constrain the +accepted DLL with `CSOKIT_NATIVE_SHA256`. + +The managed runtime rejects any library whose reported ABI is not exactly `2` before a +codec entry point is used. CI and release gates must perform native round-trip tests, not +capability discovery alone. diff --git a/docs/SECURITY_HARDENING.md b/docs/SECURITY_HARDENING.md new file mode 100644 index 0000000..28720e0 --- /dev/null +++ b/docs/SECURITY_HARDENING.md @@ -0,0 +1,57 @@ +# Security and reliability hardening + +This document records the hardening applied after the 0.6.0 architecture review. + +## Native runtime boundary + +Production resolves the native library only from `AppContext.BaseDirectory`. +Repository `artifacts` directories are ignored unless the developer explicitly sets: + +```text +CSOKIT_NATIVE_DEV_SEARCH=1 +``` + +Development search should be combined with a pinned SHA-256 value: + +```text +CSOKIT_NATIVE_SHA256=<64 hexadecimal characters> +``` + +The managed runtime requires native ABI `2` before any codec call. An absent, invalid, +hash-mismatched, or ABI-incompatible library falls back to the managed backend. + +## Cancellation + +Cancellation now crosses CLI, WPF, compression, repair, and deep-verification layers. +Long block loops check the token between blocks. Writers check cancellation again after +verification and immediately before promoting a temporary file to its final path. + +The WPF Stop action cancels the active operation. The CLI handles `Ctrl+C` for repair +and deep verification and returns exit code `130` for canceled operations. + +## Compression parallelism + +`CsoWorkerPolicy` is the single authority for worker-count validation and queue capacity. +The default is bounded by processor count, the absolute hard limit is 64, and an operator +may lower the effective maximum with `CSOKIT_MAX_WORKERS`. Queue-capacity arithmetic is checked. + +## Application boundary + +`CsoKit.Application` owns the long-running and state-changing use cases shared by CLI and WPF. +The CLI project no longer references Core directly and cannot instantiate the compressor, repairer, +or verification implementations without tripping the hardening gate. Container-reader creation is +centralized in Core. Results expose typed metrics, operation DTOs, and typed detail lines. Rendered +text is derived from those records; WPF no longer parses English result text to recover data. + +## Native release verification + +CI builds the native backend before managed tests and copies it to the test output. +Native integration tests fail when the DLL or ABI is unavailable and perform actual +raw-deflate/inflate round trips. The release publisher repeats a round trip through the +published CLI before producing the SHA-256 manifest and ZIP. + +## Version source + +The product version is stored once in the root `VERSION` file. MSBuild reads it through +`Directory.Build.props`; CMake generates native version constants from the same value; +release scripts use the same file when no explicit version is supplied. diff --git a/docs/archive/CHANGELOG_FIX_NOTES.md b/docs/archive/CHANGELOG_FIX_NOTES.md index c53a8ec..7b869c3 100644 --- a/docs/archive/CHANGELOG_FIX_NOTES.md +++ b/docs/archive/CHANGELOG_FIX_NOTES.md @@ -1,10 +1,10 @@ -# Hakamiq CsoKit stability fix notes +# CsoKit stability fix notes ## Release-readiness hardening - Add final publish native backend verification to the final release gate. - Make release workflow tag-only to preserve signed-tag release policy. -- Add independent Hakamiq compression benchmark coverage. +- Add independent CsoKit compression benchmark coverage. - Add 0.5.0 release scorecard with explicit blockers and required evidence. ## P2-I stable release promotion @@ -27,7 +27,7 @@ ## P2-F published EXE smoke -- Add `scripts/Run-PublishedExeSmoke.ps1` to publish and test the actual `hakamiq-cso.exe` output. +- Add `scripts/Run-PublishedExeSmoke.ps1` to publish and test the actual `csokit.exe` output. - Smoke-test help, version, native-info, JSON argument output, measure output, verify, compress, and decompress through the published executable. - Run real ISO -> CSO -> ISO SHA256 checks for `smallest`, `compat`, and `fast` using the published executable. - Keep generated smoke artifacts under `artifacts/published-exe-smoke-work` only when `-KeepArtifacts` is supplied. @@ -93,16 +93,16 @@ This source package applies the stability fixes requested after the CSO readines ## P1-D output path policy - Add same-folder default output naming for end-user conversion commands. -- Allow `hakamiq-cso compress ` to write `.cso` beside the source file. -- Allow `hakamiq-cso decompress ` to write `.iso` beside the source file. +- Allow `csokit compress ` to write `.cso` beside the source file. +- Allow `csokit decompress ` to write `.iso` beside the source file. - Avoid automatic output-folder creation. Explicit `-o` paths must point to an existing folder. -- Avoid overwriting existing files when output is auto-named. Existing targets receive ` - Hakamiq Converted`, then numbered suffixes. +- Avoid overwriting existing files when output is auto-named. Existing targets receive ` - CsoKit Converted`, then numbered suffixes. - Keep `--measure` write-free and output-path-free. ## P1-C measure layer - Add `CsoMeasureEstimator`, `CsoMeasureOptions`, and `CsoMeasureResult` for estimating CSO output size without writing a CSO file. -- Add `hakamiq-cso compress --measure` for measure-only CLI usage. +- Add `csokit compress --measure` for measure-only CLI usage. - Report original size, estimated CSO size, estimated ratio, saved/growth bytes, total blocks, compressed blocks, stored blocks, profile, fast mode, and level. - Reuse the same sector compression worker and stored-versus-compressed selector used by the writer path so estimates track current compression behavior. - Add focused tests to compare measure results with actual compression output. @@ -148,9 +148,9 @@ This source package applies the stability fixes requested after the CSO readines The editing environment used to prepare this package does not include the .NET SDK, so `dotnet build` / `dotnet test` could not be executed here. Run the normal local gates on Windows before merging: ```powershell -dotnet restore .\Hakamiq.CsoKit.slnx -r win-x64 -p:NuGetAudit=false -dotnet build .\Hakamiq.CsoKit.slnx -c Debug --no-restore -p:NuGetAudit=false -dotnet test .\Hakamiq.CsoKit.slnx -c Debug --no-build +dotnet restore .\CsoKit.slnx -r win-x64 -p:NuGetAudit=false +dotnet build .\CsoKit.slnx -c Debug --no-restore -p:NuGetAudit=false +dotnet test .\CsoKit.slnx -c Debug --no-build .\scripts\Publish-Release.ps1 .\scripts\Verify-Release.ps1 ``` @@ -160,8 +160,8 @@ dotnet test .\Hakamiq.CsoKit.slnx -c Debug --no-build - Treat native backend support as runtime availability, ABI verification, `native-info`, and fallback infrastructure only. - Reject the unproven native compression performance claim for 0.5.0 after measured native-runtime fast was slower and slightly larger than managed-runtime fast on the real PSP ISO. - Do not retain native block store hints or any native compression hot-path change in production. -- Keep `HAKAMIQ_CSO_DISABLE_NATIVE` as an explicit diagnostic and benchmark fallback switch. +- Keep `CSOKIT_DISABLE_NATIVE` as an explicit diagnostic and benchmark fallback switch. - Add `docs/R1_ARCHITECTURE_REPAIR.md` and refresh the release scorecard to separate native runtime proof from compression performance claims. -- Remove stale external benchmark notes so Hakamiq.CsoKit remains fully independent. +- Remove stale external benchmark notes so CsoKit remains fully independent. diff --git a/docs/archive/R1_ARCHITECTURE_REPAIR.md b/docs/archive/R1_ARCHITECTURE_REPAIR.md index f8f9c2a..8f28b1a 100644 --- a/docs/archive/R1_ARCHITECTURE_REPAIR.md +++ b/docs/archive/R1_ARCHITECTURE_REPAIR.md @@ -16,7 +16,7 @@ Measured real-ISO evidence did not prove that native participation made compress - Native DLL build and final publish inclusion. - `native-info` runtime reporting. -- Managed fallback via `HAKAMIQ_CSO_DISABLE_NATIVE` for diagnostics and benchmarks. +- Managed fallback via `CSOKIT_DISABLE_NATIVE` for diagnostics and benchmarks. - Final release gate verification that the release package loads the native backend. - Benchmark support for comparing native-runtime and managed-runtime modes. diff --git a/docs/archive/R3C_RELEASE_HARDENING.md b/docs/archive/R3C_RELEASE_HARDENING.md index daf328f..19a4274 100644 --- a/docs/archive/R3C_RELEASE_HARDENING.md +++ b/docs/archive/R3C_RELEASE_HARDENING.md @@ -1,4 +1,4 @@ -# Hakamiq.CsoKit R3-C Release Hardening +# CsoKit R3-C Release Hardening R3-C turns the R3-B container work into a stricter intake, verify, repair, normalize, and diagnostics pass. The project remains self-contained: no release gate, test, or script depends on external comparison tools. @@ -28,8 +28,8 @@ R3-C does not prove every game image, every malformed dump, or every emulator-sp Run the normal release gate first: ```powershell -dotnet build Hakamiq.CsoKit.slnx --no-restore -dotnet test Hakamiq.CsoKit.slnx --no-build --no-restore +dotnet build CsoKit.slnx --no-restore +dotnet test CsoKit.slnx --no-build --no-restore scripts/Run-ReleaseGate.ps1 -SkipRealIsoGates scripts/Test-RepoTextEncoding.ps1 ``` diff --git a/docs/archive/R3D_BENCHMARK_TRUTH.md b/docs/archive/R3D_BENCHMARK_TRUTH.md index 73dc169..caeebe6 100644 --- a/docs/archive/R3D_BENCHMARK_TRUTH.md +++ b/docs/archive/R3D_BENCHMARK_TRUTH.md @@ -1,4 +1,4 @@ -# Hakamiq.CsoKit R3-D Benchmark Truth +# CsoKit R3-D Benchmark Truth R3-D adds a local evidence layer for compression and normalization decisions. It does not add external comparison dependencies, does not store a corpus in Git, and does not change the default game-safe CSO1 output target. @@ -79,7 +79,7 @@ Not proven: Correct support statement: -Hakamiq.CsoKit reads supported readable containers, rejects corruption clearly, normalizes to CSO1 game-safe output by default, verifies output when requested or required by policy, and can produce local benchmark evidence for developer-owned files. +CsoKit reads supported readable containers, rejects corruption clearly, normalizes to CSO1 game-safe output by default, verifies output when requested or required by policy, and can produce local benchmark evidence for developer-owned files. ## R3-E clarification After R3-E, the benchmark truth layer treats container inputs and ISO inputs differently. CSO1, CSO2, ZSO, and DAX inputs prove game-safe repair/normalization only; non-game-safe profiles on those inputs are reported as skipped because `repair` supports game-safe normalization only. Use raw ISO input when the goal is profile comparison. diff --git a/docs/archive/R3E_REAL_CORPUS_EVIDENCE.md b/docs/archive/R3E_REAL_CORPUS_EVIDENCE.md index 2661d78..240a5e1 100644 --- a/docs/archive/R3E_REAL_CORPUS_EVIDENCE.md +++ b/docs/archive/R3E_REAL_CORPUS_EVIDENCE.md @@ -1,6 +1,6 @@ -# Hakamiq.CsoKit R3-E Real Corpus Evidence and Deflate Backend Calibration +# CsoKit R3-E Real Corpus Evidence and Deflate Backend Calibration -R3-E keeps Hakamiq.CsoKit scoped to PSP CSO workflows. It does not add Zstandard, LZ4, FLAC, CHD logic, emulator settings, or external executable dependencies. CSO1 remains the safe output target and the game-safe repair/normalization path remains conservative. +R3-E keeps CsoKit scoped to PSP CSO workflows. It does not add Zstandard, LZ4, FLAC, CHD logic, emulator settings, or external executable dependencies. CSO1 remains the safe output target and the game-safe repair/normalization path remains conservative. ## Benchmark truth corrections diff --git a/docs/archive/RELEASE_0_5_0_SCORECARD.md b/docs/archive/RELEASE_0_5_0_SCORECARD.md index 65e7e53..43ea654 100644 --- a/docs/archive/RELEASE_0_5_0_SCORECARD.md +++ b/docs/archive/RELEASE_0_5_0_SCORECARD.md @@ -1,4 +1,4 @@ -# Hakamiq.CsoKit Historical Scorecard +# CsoKit Historical Scorecard This historical file is superseded by `docs/RELEASE_SCORECARD.md` for the current R3-C release-hardening state. diff --git a/docs/archive/RELEASE_SCORECARD.md b/docs/archive/RELEASE_SCORECARD.md index fb86e66..5e9d4e8 100644 --- a/docs/archive/RELEASE_SCORECARD.md +++ b/docs/archive/RELEASE_SCORECARD.md @@ -1,4 +1,4 @@ -# Hakamiq.CsoKit Release Scorecard — R3-D +# CsoKit Release Scorecard — R3-D ## Current status @@ -40,8 +40,8 @@ git status --short # Run the local forbidden external-comparison hook scan before release. scripts/Test-RepoTextEncoding.ps1 scripts/Build-Native.ps1 -Configuration Release -Platform x64 -dotnet build Hakamiq.CsoKit.slnx --no-restore -dotnet test Hakamiq.CsoKit.slnx --no-build --no-restore +dotnet build CsoKit.slnx --no-restore +dotnet test CsoKit.slnx --no-build --no-restore scripts/Run-ReleaseGate.ps1 -SkipRealIsoGates ``` diff --git a/docs/release/RELEASE_0_6_0_GATE.md b/docs/release/RELEASE_0_6_0_GATE.md index 60eeb30..28b86ed 100644 --- a/docs/release/RELEASE_0_6_0_GATE.md +++ b/docs/release/RELEASE_0_6_0_GATE.md @@ -1,4 +1,4 @@ -# Hakamiq CsoKit 0.6.0 Official Release Gate +# CsoKit 0.6.0 Official Release Gate This gate validates the release candidate before publishing GitHub assets. diff --git a/native/Hakamiq.Cso.Native/CMakeLists.txt b/native/CsoKit.Native/CMakeLists.txt similarity index 63% rename from native/Hakamiq.Cso.Native/CMakeLists.txt rename to native/CsoKit.Native/CMakeLists.txt index 07d04d4..3f6dce2 100644 --- a/native/Hakamiq.Cso.Native/CMakeLists.txt +++ b/native/CsoKit.Native/CMakeLists.txt @@ -1,10 +1,23 @@ cmake_minimum_required(VERSION 3.25) -project(Hakamiq.Cso.Native - VERSION 0.6.0 +file(READ "${CMAKE_CURRENT_SOURCE_DIR}/../../VERSION" CSOKIT_VERSION) +string(STRIP "${CSOKIT_VERSION}" CSOKIT_VERSION) + +if (NOT CSOKIT_VERSION MATCHES "^[0-9]+[.][0-9]+[.][0-9]+$") + message(FATAL_ERROR "VERSION must contain a stable semantic version. Actual: ${CSOKIT_VERSION}") +endif() + +project(CsoKit.Native + VERSION ${CSOKIT_VERSION} LANGUAGES C CXX ) +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/include/csokit_version.h.in + ${CMAKE_CURRENT_BINARY_DIR}/generated/csokit_version.h + @ONLY +) + include(FetchContent) set(ZLIB_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) @@ -50,54 +63,55 @@ set(ZOPFLI_SOURCES ${ZOPFLI_ROOT}/src/zopfli/zopfli_lib.c ) -add_library(hakamiq_zopfli STATIC +add_library(csokit_zopfli STATIC ${ZOPFLI_SOURCES} ) -target_include_directories(hakamiq_zopfli +target_include_directories(csokit_zopfli PUBLIC ${ZOPFLI_ROOT}/src ) -add_library(Hakamiq.Cso.Native SHARED - src/hakamiq_cso_native.cpp +add_library(CsoKit.Native SHARED + src/csokit_native.cpp ) -target_include_directories(Hakamiq.Cso.Native +target_include_directories(CsoKit.Native PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_BINARY_DIR}/generated ${ZOPFLI_ROOT}/src ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR} ) if (TARGET zlibstatic) - set(HAKAMIQ_ZLIB_TARGET zlibstatic) + set(CSOKIT_ZLIB_TARGET zlibstatic) elseif (TARGET zlib) - set(HAKAMIQ_ZLIB_TARGET zlib) + set(CSOKIT_ZLIB_TARGET zlib) else() message(FATAL_ERROR "zlib CMake target was not found.") endif() if (TARGET libdeflate_static) - set(HAKAMIQ_LIBDEFLATE_TARGET libdeflate_static) + set(CSOKIT_LIBDEFLATE_TARGET libdeflate_static) elseif (TARGET libdeflate) - set(HAKAMIQ_LIBDEFLATE_TARGET libdeflate) + set(CSOKIT_LIBDEFLATE_TARGET libdeflate) else() message(FATAL_ERROR "libdeflate CMake target was not found.") endif() -target_link_libraries(Hakamiq.Cso.Native +target_link_libraries(CsoKit.Native PRIVATE - hakamiq_zopfli - ${HAKAMIQ_ZLIB_TARGET} - ${HAKAMIQ_LIBDEFLATE_TARGET} + csokit_zopfli + ${CSOKIT_ZLIB_TARGET} + ${CSOKIT_LIBDEFLATE_TARGET} ) -target_compile_features(Hakamiq.Cso.Native PRIVATE cxx_std_20) +target_compile_features(CsoKit.Native PRIVATE cxx_std_20) if (MSVC) - target_compile_options(Hakamiq.Cso.Native PRIVATE + target_compile_options(CsoKit.Native PRIVATE /W4 /WX /permissive- @@ -105,12 +119,12 @@ if (MSVC) /utf-8 ) - target_compile_definitions(Hakamiq.Cso.Native PRIVATE + target_compile_definitions(CsoKit.Native PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX ) endif() -set_target_properties(Hakamiq.Cso.Native PROPERTIES - OUTPUT_NAME "Hakamiq.Cso.Native" +set_target_properties(CsoKit.Native PROPERTIES + OUTPUT_NAME "CsoKit.Native" ) diff --git a/native/CsoKit.Native/include/csokit_native.h b/native/CsoKit.Native/include/csokit_native.h new file mode 100644 index 0000000..94e1ee6 --- /dev/null +++ b/native/CsoKit.Native/include/csokit_native.h @@ -0,0 +1,95 @@ +#pragma once + +#include +#include + +#if defined(_WIN32) + #if defined(CSOKIT_NATIVE_EXPORTS) + #define CSOKIT_API __declspec(dllexport) + #else + #define CSOKIT_API __declspec(dllimport) + #endif +#else + #define CSOKIT_API +#endif + +extern "C" +{ + enum CsoKitNativeStatus : int32_t + { + CSOKIT_NATIVE_OK = 0, + CSOKIT_NATIVE_UNSUPPORTED_PLATFORM = 1, + CSOKIT_NATIVE_INVALID_ARGUMENT = 2, + CSOKIT_NATIVE_OUTPUT_TOO_SMALL = 3, + CSOKIT_NATIVE_CODEC_UNAVAILABLE = 4, + CSOKIT_NATIVE_INTERNAL_ERROR = 100 + }; + + enum CsoKitCodec : int32_t + { + CSOKIT_CODEC_ZLIB_DEFAULT = 1, + CSOKIT_CODEC_ZLIB_FILTERED = 2, + CSOKIT_CODEC_ZLIB_HUFFMAN_ONLY = 3, + CSOKIT_CODEC_ZLIB_RLE = 4, + + CSOKIT_CODEC_LIBDEFLATE = 10, + CSOKIT_CODEC_ZOPFLI = 20, + CSOKIT_CODEC_7Z_DEFLATE = 30 + }; + + struct CsoKitNativeVersion + { + uint32_t abi_version; + uint32_t major; + uint32_t minor; + uint32_t patch; + }; + + struct CsoKitNativeCapabilities + { + uint32_t abi_version; + uint32_t has_zlib; + uint32_t has_libdeflate; + uint32_t has_zopfli; + uint32_t has_7z_deflate; + uint32_t has_lz4; + }; + + CSOKIT_API int32_t csokit_native_probe(); + + CSOKIT_API int32_t csokit_native_get_version( + CsoKitNativeVersion* version + ); + + CSOKIT_API int32_t csokit_native_get_capabilities( + CsoKitNativeCapabilities* capabilities + ); + + CSOKIT_API int32_t csokit_native_deflate_raw( + int32_t codec, + int32_t level, + int32_t strategy, + const uint8_t* input, + size_t input_size, + uint8_t* output, + size_t output_capacity, + size_t* output_size + ); + + CSOKIT_API int32_t csokit_native_inflate_raw( + const uint8_t* input, + size_t input_size, + uint8_t* output, + size_t output_capacity, + size_t* output_size + ); + + CSOKIT_API int32_t csokit_native_deflate_zopfli( + const uint8_t* input, + size_t input_size, + int32_t iterations, + uint8_t* output, + size_t output_capacity, + size_t* output_size + ); +} diff --git a/native/CsoKit.Native/include/csokit_version.h.in b/native/CsoKit.Native/include/csokit_version.h.in new file mode 100644 index 0000000..9530e12 --- /dev/null +++ b/native/CsoKit.Native/include/csokit_version.h.in @@ -0,0 +1,6 @@ +#pragma once + +#define CSOKIT_NATIVE_ABI_VERSION 2u +#define CSOKIT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@u +#define CSOKIT_VERSION_MINOR @PROJECT_VERSION_MINOR@u +#define CSOKIT_VERSION_PATCH @PROJECT_VERSION_PATCH@u diff --git a/native/Hakamiq.Cso.Native/src/hakamiq_cso_native.cpp b/native/CsoKit.Native/src/csokit_native.cpp similarity index 73% rename from native/Hakamiq.Cso.Native/src/hakamiq_cso_native.cpp rename to native/CsoKit.Native/src/csokit_native.cpp index 3d68dc3..ed6c91e 100644 --- a/native/Hakamiq.Cso.Native/src/hakamiq_cso_native.cpp +++ b/native/CsoKit.Native/src/csokit_native.cpp @@ -1,6 +1,6 @@ -#define HAKAMIQ_CSO_NATIVE_EXPORTS +#define CSOKIT_NATIVE_EXPORTS -#include "hakamiq_cso_native.h" +#include "csokit_native.h" #include #include @@ -8,6 +8,7 @@ #include "libdeflate.h" #include "zlib.h" #include "zopfli/zopfli.h" +#include "csokit_version.h" namespace { @@ -28,7 +29,7 @@ namespace input_size > UINT_MAX || output_capacity > UINT_MAX) { - return HAKAMIQ_CSO_NATIVE_INVALID_ARGUMENT; + return CSOKIT_NATIVE_INVALID_ARGUMENT; } z_stream stream{}; @@ -42,7 +43,7 @@ namespace if (init != Z_OK) { - return HAKAMIQ_CSO_NATIVE_INTERNAL_ERROR; + return CSOKIT_NATIVE_INTERNAL_ERROR; } stream.next_in = const_cast(reinterpret_cast(input)); @@ -56,16 +57,16 @@ namespace { deflateEnd(&stream); return result == Z_OK || result == Z_BUF_ERROR - ? HAKAMIQ_CSO_NATIVE_OUTPUT_TOO_SMALL - : HAKAMIQ_CSO_NATIVE_INTERNAL_ERROR; + ? CSOKIT_NATIVE_OUTPUT_TOO_SMALL + : CSOKIT_NATIVE_INTERNAL_ERROR; } *output_size = stream.total_out; int end = deflateEnd(&stream); return end == Z_OK - ? HAKAMIQ_CSO_NATIVE_OK - : HAKAMIQ_CSO_NATIVE_INTERNAL_ERROR; + ? CSOKIT_NATIVE_OK + : CSOKIT_NATIVE_INTERNAL_ERROR; } int32_t deflate_raw_libdeflate( @@ -80,7 +81,7 @@ namespace output == nullptr || output_size == nullptr) { - return HAKAMIQ_CSO_NATIVE_INVALID_ARGUMENT; + return CSOKIT_NATIVE_INVALID_ARGUMENT; } if (level < 1) @@ -97,7 +98,7 @@ namespace if (compressor == nullptr) { - return HAKAMIQ_CSO_NATIVE_INTERNAL_ERROR; + return CSOKIT_NATIVE_INTERNAL_ERROR; } size_t written = libdeflate_deflate_compress( @@ -111,58 +112,58 @@ namespace if (written == 0) { - return HAKAMIQ_CSO_NATIVE_OUTPUT_TOO_SMALL; + return CSOKIT_NATIVE_OUTPUT_TOO_SMALL; } *output_size = written; - return HAKAMIQ_CSO_NATIVE_OK; + return CSOKIT_NATIVE_OK; } } extern "C" { - int32_t hakamiq_cso_native_probe() + int32_t csokit_native_probe() { - return HAKAMIQ_CSO_NATIVE_OK; + return CSOKIT_NATIVE_OK; } - int32_t hakamiq_cso_native_get_version( - HakamiqCsoNativeVersion* version + int32_t csokit_native_get_version( + CsoKitNativeVersion* version ) { if (version == nullptr) { - return HAKAMIQ_CSO_NATIVE_INVALID_ARGUMENT; + return CSOKIT_NATIVE_INVALID_ARGUMENT; } - version->abi_version = 2; - version->major = 0; - version->minor = 6; - version->patch = 0; + version->abi_version = CSOKIT_NATIVE_ABI_VERSION; + version->major = CSOKIT_VERSION_MAJOR; + version->minor = CSOKIT_VERSION_MINOR; + version->patch = CSOKIT_VERSION_PATCH; - return HAKAMIQ_CSO_NATIVE_OK; + return CSOKIT_NATIVE_OK; } - int32_t hakamiq_cso_native_get_capabilities( - HakamiqCsoNativeCapabilities* capabilities + int32_t csokit_native_get_capabilities( + CsoKitNativeCapabilities* capabilities ) { if (capabilities == nullptr) { - return HAKAMIQ_CSO_NATIVE_INVALID_ARGUMENT; + return CSOKIT_NATIVE_INVALID_ARGUMENT; } - capabilities->abi_version = 2; + capabilities->abi_version = CSOKIT_NATIVE_ABI_VERSION; capabilities->has_zlib = 1; capabilities->has_libdeflate = 1; capabilities->has_zopfli = 1; capabilities->has_7z_deflate = 0; capabilities->has_lz4 = 0; - return HAKAMIQ_CSO_NATIVE_OK; + return CSOKIT_NATIVE_OK; } - int32_t hakamiq_cso_native_deflate_raw( + int32_t csokit_native_deflate_raw( int32_t codec, int32_t level, int32_t strategy, @@ -177,26 +178,26 @@ extern "C" switch (codec) { - case HAKAMIQ_CSO_CODEC_ZLIB_DEFAULT: + case CSOKIT_CODEC_ZLIB_DEFAULT: return deflate_raw_zlib(level, Z_DEFAULT_STRATEGY, input, input_size, output, output_capacity, output_size); - case HAKAMIQ_CSO_CODEC_ZLIB_FILTERED: + case CSOKIT_CODEC_ZLIB_FILTERED: return deflate_raw_zlib(level, Z_FILTERED, input, input_size, output, output_capacity, output_size); - case HAKAMIQ_CSO_CODEC_ZLIB_HUFFMAN_ONLY: + case CSOKIT_CODEC_ZLIB_HUFFMAN_ONLY: return deflate_raw_zlib(level, Z_HUFFMAN_ONLY, input, input_size, output, output_capacity, output_size); - case HAKAMIQ_CSO_CODEC_ZLIB_RLE: + case CSOKIT_CODEC_ZLIB_RLE: return deflate_raw_zlib(level, Z_RLE, input, input_size, output, output_capacity, output_size); - case HAKAMIQ_CSO_CODEC_LIBDEFLATE: + case CSOKIT_CODEC_LIBDEFLATE: return deflate_raw_libdeflate(level, input, input_size, output, output_capacity, output_size); - case HAKAMIQ_CSO_CODEC_ZOPFLI: + case CSOKIT_CODEC_ZOPFLI: break; default: - return HAKAMIQ_CSO_NATIVE_CODEC_UNAVAILABLE; + return CSOKIT_NATIVE_CODEC_UNAVAILABLE; } int32_t iterations = level; @@ -208,10 +209,10 @@ extern "C" if (iterations > 100) { - return HAKAMIQ_CSO_NATIVE_INVALID_ARGUMENT; + return CSOKIT_NATIVE_INVALID_ARGUMENT; } - return hakamiq_cso_native_deflate_zopfli( + return csokit_native_deflate_zopfli( input, input_size, iterations, @@ -220,7 +221,7 @@ extern "C" output_size); } - int32_t hakamiq_cso_native_inflate_raw( + int32_t csokit_native_inflate_raw( const uint8_t* input, size_t input_size, uint8_t* output, @@ -234,7 +235,7 @@ extern "C" input_size > UINT_MAX || output_capacity > UINT_MAX) { - return HAKAMIQ_CSO_NATIVE_INVALID_ARGUMENT; + return CSOKIT_NATIVE_INVALID_ARGUMENT; } z_stream stream{}; @@ -242,7 +243,7 @@ extern "C" if (init != Z_OK) { - return HAKAMIQ_CSO_NATIVE_INTERNAL_ERROR; + return CSOKIT_NATIVE_INTERNAL_ERROR; } stream.next_in = const_cast(reinterpret_cast(input)); @@ -256,19 +257,19 @@ extern "C" { inflateEnd(&stream); return result == Z_OK || result == Z_BUF_ERROR - ? HAKAMIQ_CSO_NATIVE_OUTPUT_TOO_SMALL - : HAKAMIQ_CSO_NATIVE_INTERNAL_ERROR; + ? CSOKIT_NATIVE_OUTPUT_TOO_SMALL + : CSOKIT_NATIVE_INTERNAL_ERROR; } *output_size = stream.total_out; int end = inflateEnd(&stream); return end == Z_OK - ? HAKAMIQ_CSO_NATIVE_OK - : HAKAMIQ_CSO_NATIVE_INTERNAL_ERROR; + ? CSOKIT_NATIVE_OK + : CSOKIT_NATIVE_INTERNAL_ERROR; } - int32_t hakamiq_cso_native_deflate_zopfli( + int32_t csokit_native_deflate_zopfli( const uint8_t* input, size_t input_size, int32_t iterations, @@ -283,7 +284,7 @@ extern "C" iterations < 1 || iterations > 100) { - return HAKAMIQ_CSO_NATIVE_INVALID_ARGUMENT; + return CSOKIT_NATIVE_INVALID_ARGUMENT; } ZopfliOptions options; @@ -308,13 +309,13 @@ extern "C" if (zopfli_output == nullptr && zopfli_output_size != 0) { - return HAKAMIQ_CSO_NATIVE_INTERNAL_ERROR; + return CSOKIT_NATIVE_INTERNAL_ERROR; } if (zopfli_output_size > output_capacity) { std::free(zopfli_output); - return HAKAMIQ_CSO_NATIVE_OUTPUT_TOO_SMALL; + return CSOKIT_NATIVE_OUTPUT_TOO_SMALL; } if (zopfli_output_size > 0) @@ -324,6 +325,6 @@ extern "C" std::free(zopfli_output); - return HAKAMIQ_CSO_NATIVE_OK; + return CSOKIT_NATIVE_OK; } } diff --git a/native/Hakamiq.Cso.Native/include/hakamiq_cso_native.h b/native/Hakamiq.Cso.Native/include/hakamiq_cso_native.h deleted file mode 100644 index fe743b7..0000000 --- a/native/Hakamiq.Cso.Native/include/hakamiq_cso_native.h +++ /dev/null @@ -1,95 +0,0 @@ -#pragma once - -#include -#include - -#if defined(_WIN32) - #if defined(HAKAMIQ_CSO_NATIVE_EXPORTS) - #define HAKAMIQ_CSO_API __declspec(dllexport) - #else - #define HAKAMIQ_CSO_API __declspec(dllimport) - #endif -#else - #define HAKAMIQ_CSO_API -#endif - -extern "C" -{ - enum HakamiqCsoNativeStatus : int32_t - { - HAKAMIQ_CSO_NATIVE_OK = 0, - HAKAMIQ_CSO_NATIVE_UNSUPPORTED_PLATFORM = 1, - HAKAMIQ_CSO_NATIVE_INVALID_ARGUMENT = 2, - HAKAMIQ_CSO_NATIVE_OUTPUT_TOO_SMALL = 3, - HAKAMIQ_CSO_NATIVE_CODEC_UNAVAILABLE = 4, - HAKAMIQ_CSO_NATIVE_INTERNAL_ERROR = 100 - }; - - enum HakamiqCsoCodec : int32_t - { - HAKAMIQ_CSO_CODEC_ZLIB_DEFAULT = 1, - HAKAMIQ_CSO_CODEC_ZLIB_FILTERED = 2, - HAKAMIQ_CSO_CODEC_ZLIB_HUFFMAN_ONLY = 3, - HAKAMIQ_CSO_CODEC_ZLIB_RLE = 4, - - HAKAMIQ_CSO_CODEC_LIBDEFLATE = 10, - HAKAMIQ_CSO_CODEC_ZOPFLI = 20, - HAKAMIQ_CSO_CODEC_7Z_DEFLATE = 30 - }; - - struct HakamiqCsoNativeVersion - { - uint32_t abi_version; - uint32_t major; - uint32_t minor; - uint32_t patch; - }; - - struct HakamiqCsoNativeCapabilities - { - uint32_t abi_version; - uint32_t has_zlib; - uint32_t has_libdeflate; - uint32_t has_zopfli; - uint32_t has_7z_deflate; - uint32_t has_lz4; - }; - - HAKAMIQ_CSO_API int32_t hakamiq_cso_native_probe(); - - HAKAMIQ_CSO_API int32_t hakamiq_cso_native_get_version( - HakamiqCsoNativeVersion* version - ); - - HAKAMIQ_CSO_API int32_t hakamiq_cso_native_get_capabilities( - HakamiqCsoNativeCapabilities* capabilities - ); - - HAKAMIQ_CSO_API int32_t hakamiq_cso_native_deflate_raw( - int32_t codec, - int32_t level, - int32_t strategy, - const uint8_t* input, - size_t input_size, - uint8_t* output, - size_t output_capacity, - size_t* output_size - ); - - HAKAMIQ_CSO_API int32_t hakamiq_cso_native_inflate_raw( - const uint8_t* input, - size_t input_size, - uint8_t* output, - size_t output_capacity, - size_t* output_size - ); - - HAKAMIQ_CSO_API int32_t hakamiq_cso_native_deflate_zopfli( - const uint8_t* input, - size_t input_size, - int32_t iterations, - uint8_t* output, - size_t output_capacity, - size_t* output_size - ); -} diff --git a/scripts/Build-Native.ps1 b/scripts/Build-Native.ps1 index 2272a5d..c252493 100644 --- a/scripts/Build-Native.ps1 +++ b/scripts/Build-Native.ps1 @@ -56,9 +56,9 @@ function Assert-NativeSourceLayout { ) $requiredFiles = @( - "native\Hakamiq.Cso.Native\CMakeLists.txt", - "native\Hakamiq.Cso.Native\src\hakamiq_cso_native.cpp", - "native\Hakamiq.Cso.Native\include\hakamiq_cso_native.h", + "native\CsoKit.Native\CMakeLists.txt", + "native\CsoKit.Native\src\csokit_native.cpp", + "native\CsoKit.Native\include\csokit_native.h", "native\third_party\zopfli\src\zopfli\zopfli_lib.c" ) @@ -104,10 +104,10 @@ if ($Platform -ne "x64") { } $repoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path -$nativeRoot = Join-Path $repoRoot "native\Hakamiq.Cso.Native" +$nativeRoot = Join-Path $repoRoot "native\CsoKit.Native" $buildDir = Join-Path $repoRoot "artifacts\native-build\win-x64" -Write-Host "Hakamiq CsoKit Native Builder" +Write-Host "CsoKit Native Builder" Write-Host "Configuration: $Configuration" Write-Host "Platform: $Platform" Write-Host "" @@ -161,7 +161,7 @@ if (-not $directBuildSucceeded) { } } -$dllPath = Join-Path $buildDir "$Configuration\Hakamiq.Cso.Native.dll" +$dllPath = Join-Path $buildDir "$Configuration\CsoKit.Native.dll" if (-not (Test-Path -LiteralPath $dllPath -PathType Leaf)) { throw "Native DLL was not produced: $dllPath" diff --git a/scripts/OutputFileNamePolicy.ps1 b/scripts/OutputFileNamePolicy.ps1 new file mode 100644 index 0000000..34dae50 --- /dev/null +++ b/scripts/OutputFileNamePolicy.ps1 @@ -0,0 +1,32 @@ +function Get-CsoKitOutputFileNameLength { + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [string]$Path + ) + + $baseName = [System.IO.Path]::GetFileNameWithoutExtension($Path) + + if ([string]::IsNullOrWhiteSpace($baseName)) { + return 0 + } + + return [System.Globalization.StringInfo]::ParseCombiningCharacters($baseName).Length +} + +function Assert-CsoKitOutputFileName { + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [string]$Path, + + [string]$Context = "Generated output" + ) + + $baseName = [System.IO.Path]::GetFileNameWithoutExtension($Path) + $length = Get-CsoKitOutputFileNameLength -Path $Path + + if ($length -lt 2 -or $length -gt 10) { + throw "$Context file name '$baseName' contains $length Unicode text elements; expected 2 to 10. Path: $Path" + } +} diff --git a/scripts/Publish-Release.ps1 b/scripts/Publish-Release.ps1 index a624e18..9530b10 100644 --- a/scripts/Publish-Release.ps1 +++ b/scripts/Publish-Release.ps1 @@ -1,66 +1,73 @@ [CmdletBinding()] param( -[string]$Version = "0.6.0", -[string]$Runtime = "win-x64" + [string]$Version = "", + [string]$Runtime = "win-x64" ) $ErrorActionPreference = "Stop" +. (Join-Path $PSScriptRoot "OutputFileNamePolicy.ps1") + function Invoke-Checked { -param( -[string]$StepName, -[scriptblock]$Command -) + param( + [string]$StepName, + [scriptblock]$Command + ) -& $Command - -if ($LASTEXITCODE -ne 0) { - throw "$StepName failed with exit code $LASTEXITCODE." -} + & $Command + if ($LASTEXITCODE -ne 0) { + throw "$StepName failed with exit code $LASTEXITCODE." + } } function Get-RelativePathCompat { -param( -[string]$BasePath, -[string]$FullPath -) - -$baseFullPath = [System.IO.Path]::GetFullPath($BasePath).TrimEnd('\', '/') + [System.IO.Path]::DirectorySeparatorChar -$itemFullPath = [System.IO.Path]::GetFullPath($FullPath) + param( + [string]$BasePath, + [string]$FullPath + ) -$baseUri = New-Object System.Uri($baseFullPath) -$itemUri = New-Object System.Uri($itemFullPath) - -$relativeUri = $baseUri.MakeRelativeUri($itemUri) -$relativePath = [System.Uri]::UnescapeDataString($relativeUri.ToString()) + $baseFullPath = [System.IO.Path]::GetFullPath($BasePath).TrimEnd('\', '/') + [System.IO.Path]::DirectorySeparatorChar + $itemFullPath = [System.IO.Path]::GetFullPath($FullPath) + $baseUri = [System.Uri]::new($baseFullPath) + $itemUri = [System.Uri]::new($itemFullPath) + $relativeUri = $baseUri.MakeRelativeUri($itemUri) + return [System.Uri]::UnescapeDataString($relativeUri.ToString()).Replace('\', '/') +} -return $relativePath.Replace('\', '/') +$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path +$versionFile = Join-Path $RepoRoot "VERSION" +if ([string]::IsNullOrWhiteSpace($Version)) { + $Version = (Get-Content -LiteralPath $versionFile -Raw).Trim() } -$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path +if ([string]::IsNullOrWhiteSpace($Version)) { + throw "VERSION is empty." +} $SolutionFile = Get-ChildItem -Path $RepoRoot -File | -Where-Object { $_.Extension -in ".sln", ".slnx" } | -Select-Object -First 1 + Where-Object { $_.Extension -in ".sln", ".slnx" } | + Select-Object -First 1 if (-not $SolutionFile) { -throw "No .sln or .slnx file was found in repo root: $RepoRoot" + throw "No .sln or .slnx file was found in repo root: $RepoRoot" } if ($Runtime -ne "win-x64") { -throw "Native backend packaging currently supports win-x64 only. Runtime requested: $Runtime" + throw "Native backend packaging currently supports win-x64 only. Runtime requested: $Runtime" } $Solution = $SolutionFile.FullName -$CliProject = Join-Path $RepoRoot "src\Hakamiq.Cso.Cli\Hakamiq.Cso.Cli.csproj" +$CliProject = Join-Path $RepoRoot "src\CsoKit.Cli\CsoKit.Cli.csproj" $ArtifactsDir = Join-Path $RepoRoot "artifacts" $PublishDir = Join-Path (Join-Path $ArtifactsDir "publish") $Runtime $ReleaseDir = Join-Path $ArtifactsDir "release" -$ZipPath = Join-Path $ReleaseDir "hakamiq-csokit-$Version-$Runtime.zip" +$ZipPath = Join-Path $ReleaseDir "csokit-$Version-$Runtime.zip" +$NativeDllPath = Join-Path $ArtifactsDir "native-build\win-x64\Release\CsoKit.Native.dll" +$TestNativeDllPath = Join-Path $RepoRoot "tests\CsoKit.Tests\bin\Release\net10.0\CsoKit.Native.dll" -Write-Host "Hakamiq CsoKit Release Publisher" +Write-Host "CsoKit Release Publisher" Write-Host "Version: $Version" Write-Host "Runtime: $Runtime" Write-Host "Solution: $Solution" @@ -70,175 +77,150 @@ Remove-Item $ArtifactsDir -Recurse -Force -ErrorAction SilentlyContinue New-Item -ItemType Directory -Force $PublishDir | Out-Null New-Item -ItemType Directory -Force $ReleaseDir | Out-Null -Write-Host "[1/8] Restore" +Write-Host "[1/9] Restore" Invoke-Checked "Restore" { -$args = @( -"restore", -$Solution, -"-r", -$Runtime, -"-p:NuGetAudit=false" -) + dotnet restore $Solution -r $Runtime -p:NuGetAudit=false +} -dotnet @args +Write-Host "[2/9] Build native backend" +& "$PSScriptRoot\Build-Native.ps1" -Configuration Release -Platform x64 +if (-not (Test-Path -LiteralPath $NativeDllPath -PathType Leaf)) { + throw "Native DLL was not produced: $NativeDllPath" } -Write-Host "[2/8] Build Release" +Write-Host "[3/9] Build Release" Invoke-Checked "Build Release" { -$args = @( -"build", -$Solution, -"-c", -"Release", -"--no-restore", -"-p:NuGetAudit=false", -"-p:Version=$Version" -) - -dotnet @args - + dotnet build $Solution -c Release --no-restore -p:NuGetAudit=false -p:Version=$Version } -Write-Host "[3/8] Test Release" -Invoke-Checked "Test Release" { -$args = @( -"test", -$Solution, -"-c", -"Release", -"--no-build" -) - -dotnet @args - +Write-Host "[4/9] Stage native backend and test Release" +New-Item -ItemType Directory -Force (Split-Path -Parent $TestNativeDllPath) | Out-Null +Copy-Item -LiteralPath $NativeDllPath -Destination $TestNativeDllPath -Force +Invoke-Checked "Test Release with native integration" { + dotnet test $Solution -c Release --no-build } -Write-Host "[4/8] Publish single-file CLI" +Write-Host "[5/9] Publish single-file CLI" Invoke-Checked "Publish CLI" { -$args = @( -"publish", -$CliProject, -"-c", -"Release", -"-r", -$Runtime, -"--self-contained", -"true", -"-o", -$PublishDir, -"-p:PublishSingleFile=true", -"-p:EnableCompressionInSingleFile=true", -"-p:PublishTrimmed=false", -"-p:DebugType=None", -"-p:DebugSymbols=false", -"-p:Version=$Version", -"-p:NuGetAudit=false" -) - -dotnet @args - -} - -$ExePath = Join-Path $PublishDir "hakamiq-cso.exe" - -if (-not (Test-Path $ExePath)) { -throw "Published executable was not found: $ExePath" -} - -Write-Host "[5/8] Build and copy native backend" - -& "$PSScriptRoot\Build-Native.ps1" -Configuration Release -Platform x64 - -$NativeDllPath = Join-Path $ArtifactsDir "native-build\win-x64\Release\Hakamiq.Cso.Native.dll" -$PublishNativeDllPath = Join-Path $PublishDir "Hakamiq.Cso.Native.dll" - -if (-not (Test-Path $NativeDllPath)) { -throw "Native DLL was not produced: $NativeDllPath" + dotnet publish $CliProject ` + -c Release ` + -r $Runtime ` + --self-contained true ` + -o $PublishDir ` + -p:PublishSingleFile=true ` + -p:EnableCompressionInSingleFile=true ` + -p:PublishTrimmed=false ` + -p:DebugType=None ` + -p:DebugSymbols=false ` + -p:Version=$Version ` + -p:NuGetAudit=false } -Copy-Item $NativeDllPath $PublishNativeDllPath -Force +$ExePath = Join-Path $PublishDir "csokit.exe" +$PublishNativeDllPath = Join-Path $PublishDir "CsoKit.Native.dll" -if (-not (Test-Path $PublishNativeDllPath)) { -throw "Native DLL was not copied to publish directory: $PublishNativeDllPath" +if (-not (Test-Path -LiteralPath $ExePath -PathType Leaf)) { + throw "Published executable was not found: $ExePath" } +Write-Host "[6/9] Copy runtime dependencies and notices" +Copy-Item -LiteralPath $NativeDllPath -Destination $PublishNativeDllPath -Force Copy-Item (Join-Path $RepoRoot "README.md") (Join-Path $PublishDir "README.md") -Force Copy-Item (Join-Path $RepoRoot "LICENSE.txt") (Join-Path $PublishDir "LICENSE.txt") -Force Copy-Item (Join-Path $RepoRoot "THIRD_PARTY_NOTICES.md") (Join-Path $PublishDir "THIRD_PARTY_NOTICES.md") -Force $ReleaseNotesPath = Join-Path $RepoRoot "RELEASE_NOTES.md" -if (Test-Path $ReleaseNotesPath) { +if (Test-Path -LiteralPath $ReleaseNotesPath -PathType Leaf) { Copy-Item $ReleaseNotesPath (Join-Path $PublishDir "RELEASE_NOTES.md") -Force } -Write-Host "[6/8] Smoke test" - +Write-Host "[7/9] CLI and native capability smoke" $versionText = ((& $ExePath --version) | Out-String).Trim() -if ($LASTEXITCODE -ne 0) { -throw "Version smoke test failed." -} - -if ($versionText -notmatch [regex]::Escape($Version)) { -throw "Version output does not contain expected version. Output: $versionText" +if ($LASTEXITCODE -ne 0 -or $versionText -notmatch [regex]::Escape($Version)) { + throw "Version smoke test failed. Output: $versionText" } $helpText = ((& $ExePath --help) | Out-String).Trim() if ($LASTEXITCODE -ne 0) { -throw "Help smoke test failed." + throw "Help smoke test failed." } foreach ($required in @("info", "verify", "repair", "analyze", "detect", "decompress", "compress", "codecs", "native-info", "--json", "--quiet", "--profile", "--threads", "--block", "--zopfli", "--codec-report", "game-safe|compat|fast|smallest|archive-smallest")) { -if ($helpText -notmatch [regex]::Escape($required)) { -throw "Help output does not contain required text: $required" -} + if ($helpText -notmatch [regex]::Escape($required)) { + throw "Help output does not contain required text: $required" + } } -Write-Host "[7/8] Native smoke test" - $nativeInfoOutput = ((& $ExePath native-info) | Out-String).Trim() if ($LASTEXITCODE -ne 0) { -throw "native-info smoke test failed." -} - -if ($nativeInfoOutput -notmatch "Backend:\s+native") { -Write-Host $nativeInfoOutput -throw "native-info did not report native backend." -} - -if ($nativeInfoOutput -notmatch "Native available:\s+True") { -Write-Host $nativeInfoOutput -throw "native-info did not report native availability." -} - -foreach ($requiredCapability in @( -"Native zlib:\s+available", -"Native libdeflate:\s+available", -"Native Zopfli:\s+available", -"LZ4 decode:\s+available" -)) { -if ($nativeInfoOutput -notmatch $requiredCapability) { -Write-Host $nativeInfoOutput -throw "native-info did not report required codec capability: $requiredCapability" -} -} - -Write-Host "[8/8] SHA256 manifest and ZIP" - + throw "native-info smoke test failed." +} + +foreach ($requiredPattern in @( + "Backend:\s+native", + "Native available:\s+True", + "ABI\s+2", + "Native zlib:\s+available", + "Native libdeflate:\s+available", + "Native Zopfli:\s+available")) { + if ($nativeInfoOutput -notmatch $requiredPattern) { + Write-Host $nativeInfoOutput + throw "native-info did not report required state: $requiredPattern" + } +} + +Write-Host "[8/9] Published native round-trip" +$smokeRoot = Join-Path $ArtifactsDir "published-native-roundtrip" +$inputIso = Join-Path $smokeRoot "input.iso" +$outputCso = Join-Path $smokeRoot "smoke.cso" +$restoredIso = Join-Path $smokeRoot "back.iso" +Assert-CsoKitOutputFileName -Path $outputCso -Context "Published native round-trip CSO" +Assert-CsoKitOutputFileName -Path $restoredIso -Context "Published native round-trip restored ISO" +Remove-Item -LiteralPath $smokeRoot -Recurse -Force -ErrorAction SilentlyContinue +New-Item -ItemType Directory -Force $smokeRoot | Out-Null + +$sample = [byte[]]::new(65536) +for ($index = 0; $index -lt $sample.Length; $index++) { + $sample[$index] = [byte](($index * 17) % 251) +} +[System.IO.File]::WriteAllBytes($inputIso, $sample) + +try { + & $ExePath compress $inputIso -o $outputCso --profile game-safe --threads 1 --block 2048 --zopfli --deep-verify + if ($LASTEXITCODE -ne 0) { + throw "Published native compression round-trip failed during compression." + } + + & $ExePath decompress $outputCso -o $restoredIso + if ($LASTEXITCODE -ne 0) { + throw "Published native compression round-trip failed during decompression." + } + + $inputHash = (Get-FileHash -LiteralPath $inputIso -Algorithm SHA256).Hash + $restoredHash = (Get-FileHash -LiteralPath $restoredIso -Algorithm SHA256).Hash + if ($inputHash -ne $restoredHash) { + throw "Published native round-trip SHA256 mismatch." + } +} +finally { + Remove-Item -LiteralPath $smokeRoot -Recurse -Force -ErrorAction SilentlyContinue +} + +Write-Host "[9/9] SHA256 manifest and ZIP" $ManifestPath = Join-Path $PublishDir "SHA256SUMS.txt" - Get-ChildItem $PublishDir -File -Recurse | -Where-Object { $_.Name -ne "SHA256SUMS.txt" } | -Sort-Object FullName | -ForEach-Object { -$hash = (Get-FileHash $_.FullName -Algorithm SHA256).Hash.ToLowerInvariant() -$relative = Get-RelativePathCompat -BasePath $PublishDir -FullPath $_.FullName -"$hash $relative" -} | -Set-Content $ManifestPath -Encoding UTF8 + Where-Object { $_.Name -ne "SHA256SUMS.txt" } | + Sort-Object FullName | + ForEach-Object { + $hash = (Get-FileHash $_.FullName -Algorithm SHA256).Hash.ToLowerInvariant() + $relative = Get-RelativePathCompat -BasePath $PublishDir -FullPath $_.FullName + "$hash $relative" + } | + Set-Content $ManifestPath -Encoding UTF8 if (Test-Path $ZipPath) { -Remove-Item $ZipPath -Force + Remove-Item $ZipPath -Force } Compress-Archive -Path (Join-Path $PublishDir "*") -DestinationPath $ZipPath -Force @@ -247,5 +229,3 @@ Write-Host "" Write-Host "[PASS] Release package created" Write-Host "PublishDir: $PublishDir" Write-Host "ZipPath: $ZipPath" - - diff --git a/scripts/Publish-SourcePackage.ps1 b/scripts/Publish-SourcePackage.ps1 index 03296ca..cea7f83 100644 --- a/scripts/Publish-SourcePackage.ps1 +++ b/scripts/Publish-SourcePackage.ps1 @@ -1,6 +1,6 @@ [CmdletBinding()] param( - [string]$Version = "0.6.0" + [string]$Version = "" ) $ErrorActionPreference = "Stop" @@ -42,27 +42,40 @@ function Assert-RequiredSourceFile { } $repoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path +$versionFile = Join-Path $repoRoot "VERSION" +if ([string]::IsNullOrWhiteSpace($Version)) { + $Version = (Get-Content -LiteralPath $versionFile -Raw).Trim() +} +if ([string]::IsNullOrWhiteSpace($Version)) { + throw "VERSION is empty." +} $artifactsDir = Join-Path $repoRoot "artifacts" $sourceDir = Join-Path $artifactsDir "source" -$zipPath = Join-Path $sourceDir "hakamiq-csokit-$Version-source.zip" +$zipPath = Join-Path $sourceDir "csokit-$Version-source.zip" $stagingDir = Join-Path $sourceDir "staging" $blockedTopLevel = @(".git", ".vs", "bin", "obj", "artifacts", "TestResults") $blockedNested = @("bin", "obj", "TestResults") $requiredSourceFiles = @( - "Hakamiq.CsoKit.slnx", - "src\Hakamiq.Cso.Core\Hakamiq.Cso.Core.csproj", - "src\Hakamiq.Cso.Cli\Hakamiq.Cso.Cli.csproj", - "src\Hakamiq.Cso.App\Hakamiq.Cso.App.csproj", - "tests\Hakamiq.Cso.Tests\Hakamiq.Cso.Tests.csproj", - "native\Hakamiq.Cso.Native\CMakeLists.txt", - "native\Hakamiq.Cso.Native\src\hakamiq_cso_native.cpp", - "native\Hakamiq.Cso.Native\include\hakamiq_cso_native.h", + "VERSION", + "Directory.Build.props", + "CsoKit.slnx", + "src\CsoKit.Core\CsoKit.Core.csproj", + "src\CsoKit.Application\CsoKit.Application.csproj", + "src\CsoKit.Cli\CsoKit.Cli.csproj", + "src\CsoKit.App\CsoKit.App.csproj", + "tests\CsoKit.Tests\CsoKit.Tests.csproj", + "tests\CsoKit.App.Tests\CsoKit.App.Tests.csproj", + "scripts\Verify-Hardening.ps1", + "native\CsoKit.Native\CMakeLists.txt", + "native\CsoKit.Native\src\csokit_native.cpp", + "native\CsoKit.Native\include\csokit_native.h", + "native\CsoKit.Native\include\csokit_version.h.in", "native\third_party\zopfli\src\zopfli\zopfli_lib.c" ) -Write-Host "Hakamiq CsoKit Source Package Publisher" +Write-Host "CsoKit Source Package Publisher" Write-Host "Version: $Version" Write-Host "Repo: $repoRoot" Write-Host "" @@ -86,6 +99,10 @@ $items = Get-ChildItem $repoRoot -Force -Recurse -File | Where-Object { return $false } + if ($parts.Count -eq 1 -and [System.IO.Path]::GetExtension($parts[0]) -eq ".zip") { + return $false + } + foreach ($part in $parts) { if ($blockedNested -contains $part) { return $false @@ -110,10 +127,22 @@ foreach ($relative in $relativeItems) { Copy-Item -LiteralPath $sourcePath -Destination $destinationPath -Force } -$manifestPath = Join-Path $stagingDir "SOURCE_FILES.txt" +$sourceListPath = Join-Path $stagingDir "SOURCE_FILES.txt" $relativeItems | ForEach-Object { $_.Replace([System.IO.Path]::DirectorySeparatorChar, '/') } | - Set-Content -LiteralPath $manifestPath -Encoding UTF8 + Set-Content -LiteralPath $sourceListPath -Encoding UTF8 + +$hashManifestPath = Join-Path $stagingDir "SOURCE-MANIFEST.sha256" +Get-ChildItem -LiteralPath $stagingDir -File -Recurse | + Where-Object { $_.FullName -ne $hashManifestPath } | + Sort-Object FullName | + ForEach-Object { + $hash = (Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash.ToLowerInvariant() + $relative = Get-RelativePathCompat -BasePath $stagingDir -FullPath $_.FullName + $normalized = $relative.Replace([System.IO.Path]::DirectorySeparatorChar, '/') + "$hash $normalized" + } | + Set-Content -LiteralPath $hashManifestPath -Encoding UTF8 if (Test-Path -LiteralPath $zipPath) { Remove-Item -LiteralPath $zipPath -Force diff --git a/scripts/Run-BenchmarkTruthLayer.ps1 b/scripts/Run-BenchmarkTruthLayer.ps1 index ef0c976..6db5382 100644 --- a/scripts/Run-BenchmarkTruthLayer.ps1 +++ b/scripts/Run-BenchmarkTruthLayer.ps1 @@ -65,7 +65,7 @@ function Resolve-BenchmarkProfiles { function Get-DefaultOutputDirectory { if (-not [string]::IsNullOrWhiteSpace($Root)) { $resolvedRoot = (Resolve-Path -LiteralPath $Root -ErrorAction Stop).ProviderPath - return Join-Path $resolvedRoot "HakamiqCsoKit_BenchmarkTruth" + return Join-Path $resolvedRoot "CsoKit_BenchmarkTruth" } foreach ($path in @($InputPath)) { @@ -77,13 +77,13 @@ function Get-DefaultOutputDirectory { $item = Get-Item -LiteralPath $resolvedPath -ErrorAction Stop if ($item.PSIsContainer) { - return Join-Path $item.FullName "HakamiqCsoKit_BenchmarkTruth" + return Join-Path $item.FullName "CsoKit_BenchmarkTruth" } - return Join-Path $item.Directory.FullName "HakamiqCsoKit_BenchmarkTruth" + return Join-Path $item.Directory.FullName "CsoKit_BenchmarkTruth" } - return Join-Path ([System.IO.Path]::GetTempPath()) ("HakamiqCsoKit_BenchmarkTruth_" + [Guid]::NewGuid().ToString("N")) + return Join-Path ([System.IO.Path]::GetTempPath()) ("CsoKit_BenchmarkTruth_" + [Guid]::NewGuid().ToString("N")) } function Write-Utf8NoBom { @@ -253,9 +253,9 @@ function Get-ResolvedInputFiles { function Initialize-CsoTool { $script:RepoRoot = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")).ProviderPath - $solution = Join-Path $script:RepoRoot "Hakamiq.CsoKit.slnx" - $exe = Join-Path $script:RepoRoot "src/Hakamiq.Cso.Cli/bin/$Configuration/net10.0/hakamiq-cso.exe" - $dll = Join-Path $script:RepoRoot "src/Hakamiq.Cso.Cli/bin/$Configuration/net10.0/Hakamiq.Cso.Cli.dll" + $solution = Join-Path $script:RepoRoot "CsoKit.slnx" + $exe = Join-Path $script:RepoRoot "src/CsoKit.Cli/bin/$Configuration/net10.0/csokit.exe" + $dll = Join-Path $script:RepoRoot "src/CsoKit.Cli/bin/$Configuration/net10.0/CsoKit.Cli.dll" if (-not (Test-Path -LiteralPath $exe -PathType Leaf) -and -not (Test-Path -LiteralPath $dll -PathType Leaf)) { @@ -356,7 +356,7 @@ function Invoke-JsonTool { } catch { if ($process.ExitCode -eq 0) { - throw "hakamiq-cso did not return valid JSON for: $($Arguments -join ' ')" + throw "csokit did not return valid JSON for: $($Arguments -join ' ')" } } } @@ -381,7 +381,7 @@ function Invoke-JsonTool { } if ($null -eq $json) { - throw "hakamiq-cso did not return valid JSON for: $($Arguments -join ' ')" + throw "csokit did not return valid JSON for: $($Arguments -join ' ')" } return [pscustomobject]@{ @@ -430,7 +430,7 @@ function Get-ReportMarkdown { param([object]$Report) $builder = [System.Text.StringBuilder]::new() - [void]$builder.AppendLine("# Hakamiq.CsoKit Benchmark Truth Report") + [void]$builder.AppendLine("# CsoKit Benchmark Truth Report") [void]$builder.AppendLine() [void]$builder.AppendLine("- Generated UTC: $($Report.generatedAtUtc)") [void]$builder.AppendLine("- Repo: $($Report.repo)") @@ -497,7 +497,7 @@ $artifactRoot = if ($KeepArtifacts) { Join-Path $OutputDirectory "artifacts" } else { - Join-Path ([System.IO.Path]::GetTempPath()) ("HakamiqCsoKit_BenchmarkArtifacts_" + [Guid]::NewGuid().ToString("N")) + Join-Path ([System.IO.Path]::GetTempPath()) ("CsoKit_BenchmarkArtifacts_" + [Guid]::NewGuid().ToString("N")) } New-Item -ItemType Directory -Path $artifactRoot -Force | Out-Null diff --git a/scripts/Run-FinalReleaseGate.ps1 b/scripts/Run-FinalReleaseGate.ps1 index 5f73f73..797d422 100644 --- a/scripts/Run-FinalReleaseGate.ps1 +++ b/scripts/Run-FinalReleaseGate.ps1 @@ -1,6 +1,6 @@ [CmdletBinding()] param( - [string]$Version = "0.6.0", + [string]$Version = "", [string]$Runtime = "win-x64", [string]$InputIso, [switch]$SkipRealIsoGates, @@ -113,8 +113,8 @@ function Assert-FinalNativeBackend { [string]$ExpectedVersion ) - $exePath = Join-Path $PublishDir "hakamiq-cso.exe" - $nativeDllPath = Join-Path $PublishDir "Hakamiq.Cso.Native.dll" + $exePath = Join-Path $PublishDir "csokit.exe" + $nativeDllPath = Join-Path $PublishDir "CsoKit.Native.dll" if (-not (Test-Path $exePath)) { throw "Published executable was not found for native backend check: $exePath" @@ -162,19 +162,26 @@ function Assert-FinalNativeBackend { } $RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path +$versionFile = Join-Path $RepoRoot "VERSION" +if ([string]::IsNullOrWhiteSpace($Version)) { + $Version = (Get-Content -LiteralPath $versionFile -Raw).Trim() +} +if ([string]::IsNullOrWhiteSpace($Version)) { + throw "VERSION is empty." +} $ReleaseGateScript = Join-Path $PSScriptRoot "Run-ReleaseGate.ps1" $PublishedSmokeScript = Join-Path $PSScriptRoot "Run-PublishedExeSmoke.ps1" $PublishReleaseScript = Join-Path $PSScriptRoot "Publish-Release.ps1" $VerifyReleaseScript = Join-Path $PSScriptRoot "Verify-Release.ps1" $PublishSourceScript = Join-Path $PSScriptRoot "Publish-SourcePackage.ps1" -$CliProject = Join-Path $RepoRoot "src\Hakamiq.Cso.Cli\Hakamiq.Cso.Cli.csproj" -$CoreProject = Join-Path $RepoRoot "src\Hakamiq.Cso.Core\Hakamiq.Cso.Core.csproj" -$AppProject = Join-Path $RepoRoot "src\Hakamiq.Cso.App\Hakamiq.Cso.App.csproj" +$CliProject = Join-Path $RepoRoot "src\CsoKit.Cli\CsoKit.Cli.csproj" +$CoreProject = Join-Path $RepoRoot "src\CsoKit.Core\CsoKit.Core.csproj" +$AppProject = Join-Path $RepoRoot "src\CsoKit.App\CsoKit.App.csproj" $PublishDir = Join-Path (Join-Path $RepoRoot "artifacts\publish") $Runtime -$ReleaseZip = Join-Path (Join-Path $RepoRoot "artifacts\release") "hakamiq-csokit-$Version-$Runtime.zip" -$SourceZip = Join-Path (Join-Path $RepoRoot "artifacts\source") "hakamiq-csokit-$Version-source.zip" +$ReleaseZip = Join-Path (Join-Path $RepoRoot "artifacts\release") "csokit-$Version-$Runtime.zip" +$SourceZip = Join-Path (Join-Path $RepoRoot "artifacts\source") "csokit-$Version-source.zip" -Write-Host "Hakamiq CsoKit Final Release Gate" +Write-Host "CsoKit Final Release Gate" Write-Host "---------------------------------" Write-Host "Repo: $RepoRoot" Write-Host "Version: $Version" diff --git a/scripts/Run-OfficialReleaseGate.ps1 b/scripts/Run-OfficialReleaseGate.ps1 index a26e88d..7b79180 100644 --- a/scripts/Run-OfficialReleaseGate.ps1 +++ b/scripts/Run-OfficialReleaseGate.ps1 @@ -1,6 +1,6 @@ [CmdletBinding()] param( - [string]$Version = "0.6.0", + [string]$Version = "", [string]$Runtime = "win-x64", [string]$InputIso, [switch]$SkipRealIsoGate, @@ -301,21 +301,28 @@ if ($Runtime -ne "win-x64") { } $RepoRoot = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")).Path -$SolutionPath = Join-Path $RepoRoot "Hakamiq.CsoKit.slnx" -$CoreProject = Join-Path $RepoRoot "src\Hakamiq.Cso.Core\Hakamiq.Cso.Core.csproj" -$CliProject = Join-Path $RepoRoot "src\Hakamiq.Cso.Cli\Hakamiq.Cso.Cli.csproj" -$AppProject = Join-Path $RepoRoot "src\Hakamiq.Cso.App\Hakamiq.Cso.App.csproj" -$NativeSource = Join-Path $RepoRoot "native\Hakamiq.Cso.Native\src\hakamiq_cso_native.cpp" -$NativeCMake = Join-Path $RepoRoot "native\Hakamiq.Cso.Native\CMakeLists.txt" +$versionFile = Join-Path $RepoRoot "VERSION" +if ([string]::IsNullOrWhiteSpace($Version)) { + $Version = (Get-Content -LiteralPath $versionFile -Raw).Trim() +} +if ([string]::IsNullOrWhiteSpace($Version)) { + throw "VERSION is empty." +} +$SolutionPath = Join-Path $RepoRoot "CsoKit.slnx" +$CoreProject = Join-Path $RepoRoot "src\CsoKit.Core\CsoKit.Core.csproj" +$CliProject = Join-Path $RepoRoot "src\CsoKit.Cli\CsoKit.Cli.csproj" +$AppProject = Join-Path $RepoRoot "src\CsoKit.App\CsoKit.App.csproj" +$NativeSource = Join-Path $RepoRoot "native\CsoKit.Native\src\csokit_native.cpp" +$NativeCMake = Join-Path $RepoRoot "native\CsoKit.Native\CMakeLists.txt" $ArtifactsDir = Join-Path $RepoRoot "artifacts" $PublishRoot = Join-Path $ArtifactsDir "publish" $ReleaseRoot = Join-Path $ArtifactsDir "release" -$CliPublishDir = Join-Path $PublishRoot "Hakamiq.CsoKit-cli-$Runtime" -$AppPublishDir = Join-Path $PublishRoot "Hakamiq.CsoKit-app-$Runtime" -$CliZip = Join-Path $ReleaseRoot "hakamiq-csokit-$Version-cli-$Runtime.zip" -$AppZip = Join-Path $ReleaseRoot "hakamiq-csokit-$Version-app-$Runtime.zip" +$CliPublishDir = Join-Path $PublishRoot "CsoKit-cli-$Runtime" +$AppPublishDir = Join-Path $PublishRoot "CsoKit-app-$Runtime" +$CliZip = Join-Path $ReleaseRoot "csokit-$Version-cli-$Runtime.zip" +$AppZip = Join-Path $ReleaseRoot "csokit-$Version-app-$Runtime.zip" -Write-Host "Hakamiq CsoKit Official Release Gate" +Write-Host "CsoKit Official Release Gate" Write-Host "-------------------------------------" Write-Host "Repo: $RepoRoot" Write-Host "Version: $Version" @@ -390,12 +397,12 @@ Invoke-Step "publish App" { } Invoke-Step "CLI smoke" { - Invoke-CliSmoke -ExePath (Join-Path $CliPublishDir "hakamiq-cso.exe") + Invoke-CliSmoke -ExePath (Join-Path $CliPublishDir "csokit.exe") } if (Test-ShouldRunRealIsoGate) { Invoke-Step "Raw ISO deep verify smoke" { - Invoke-RawIsoDeepVerifySmoke -ExePath (Join-Path $CliPublishDir "hakamiq-cso.exe") -IsoPath $InputIso + Invoke-RawIsoDeepVerifySmoke -ExePath (Join-Path $CliPublishDir "csokit.exe") -IsoPath $InputIso } } else { @@ -412,7 +419,7 @@ Invoke-Step "create release ZIPs" { $summaryPath = Join-Path $ReleaseRoot "RELEASE_GATE_SUMMARY.txt" @( - "Hakamiq CsoKit Official Release Gate", + "CsoKit Official Release Gate", "Version: $Version", "Runtime: $Runtime", "Timestamp: $((Get-Date).ToString('o'))", diff --git a/scripts/Run-ProfileRoundtripMatrix.ps1 b/scripts/Run-ProfileRoundtripMatrix.ps1 index 0d57b88..600f061 100644 --- a/scripts/Run-ProfileRoundtripMatrix.ps1 +++ b/scripts/Run-ProfileRoundtripMatrix.ps1 @@ -12,6 +12,8 @@ param( $ErrorActionPreference = "Stop" +. (Join-Path $PSScriptRoot "OutputFileNamePolicy.ps1") + function Get-ResolvedFilePath { param( [string]$Path, @@ -37,32 +39,7 @@ function Get-ResolvedFilePath { return $item.FullName } -function New-UniqueSiblingPath { - param( - [string]$DirectoryPath, - [string]$BaseName, - [string]$Suffix, - [string]$Extension - ) - - $candidate = Join-Path $DirectoryPath ("{0}{1}{2}" -f $BaseName, $Suffix, $Extension) - - if (-not (Test-Path -LiteralPath $candidate)) { - return $candidate - } - - for ($index = 2; $index -lt 10000; $index++) { - $candidate = Join-Path $DirectoryPath ("{0}{1} {2}{3}" -f $BaseName, $Suffix, $index, $Extension) - - if (-not (Test-Path -LiteralPath $candidate)) { - return $candidate - } - } - - throw "Could not find a free artifact name in: $DirectoryPath" -} - -function Invoke-HakamiqCso { +function Invoke-CsoKit { param( [string]$StepName, [string[]]$CommandArguments @@ -126,7 +103,7 @@ function Get-NormalizedProfiles { } $RepoRoot = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")).Path -$CliProject = Join-Path $RepoRoot "src\Hakamiq.Cso.Cli\Hakamiq.Cso.Cli.csproj" +$CliProject = Join-Path $RepoRoot "src\CsoKit.Cli\CsoKit.Cli.csproj" if (-not (Test-Path -LiteralPath $CliProject)) { throw "CLI project was not found: $CliProject" @@ -141,27 +118,28 @@ if (-not [string]::Equals($InputItem.Extension, ".iso", [System.StringComparison $ProfileList = Get-NormalizedProfiles -ProfileNames $Profiles $DirectoryPath = $InputItem.DirectoryName -$BaseName = [System.IO.Path]::GetFileNameWithoutExtension($InputItem.Name) +$WorkRoot = Join-Path $DirectoryPath (".csokit-profiles-" + [System.Guid]::NewGuid().ToString("N")) $OriginalHash = Get-Sha256Hex -Path $InputIsoPath $OriginalSize = (Get-Item -LiteralPath $InputIsoPath).Length -$Artifacts = New-Object System.Collections.Generic.List[string] $Results = New-Object System.Collections.Generic.List[object] $success = $false -Write-Host "Hakamiq CsoKit Profile Roundtrip Matrix" +Write-Host "CsoKit Profile Roundtrip Matrix" Write-Host "Input: $InputIsoPath" Write-Host "Profiles: $($ProfileList -join ', ')" Write-Host "Artifacts: $(if ($KeepArtifacts) { 'kept' } else { 'deleted on success' })" Write-Host "SHA256: $OriginalHash" try { - foreach ($profile in $ProfileList) { - $profileLabel = $profile.Substring(0, 1).ToUpperInvariant() + $profile.Substring(1) - $CsoArtifactPath = New-UniqueSiblingPath -DirectoryPath $DirectoryPath -BaseName $BaseName -Suffix " - Hakamiq $profileLabel Profile Gate" -Extension ".cso" - $RestoredIsoPath = New-UniqueSiblingPath -DirectoryPath $DirectoryPath -BaseName $BaseName -Suffix " - Hakamiq $profileLabel Profile Restored" -Extension ".iso" + New-Item -ItemType Directory -Force -Path $WorkRoot | Out-Null - $Artifacts.Add($CsoArtifactPath) | Out-Null - $Artifacts.Add($RestoredIsoPath) | Out-Null + foreach ($profile in $ProfileList) { + $profileRoot = Join-Path $WorkRoot $profile + New-Item -ItemType Directory -Force -Path $profileRoot | Out-Null + $CsoArtifactPath = Join-Path $profileRoot "out.cso" + $RestoredIsoPath = Join-Path $profileRoot "back.iso" + Assert-CsoKitOutputFileName -Path $CsoArtifactPath -Context "Profile matrix CSO" + Assert-CsoKitOutputFileName -Path $RestoredIsoPath -Context "Profile matrix restored ISO" Write-Host "" Write-Host "Profile: $profile" @@ -178,15 +156,15 @@ try { $decompressArgs += "--quiet" } - Invoke-HakamiqCso -StepName "Compress ISO to CSO ($profile)" -CommandArguments $compressArgs + Invoke-CsoKit -StepName "Compress ISO to CSO ($profile)" -CommandArguments $compressArgs if (-not (Test-Path -LiteralPath $CsoArtifactPath)) { throw "Compression completed but CSO artifact was not found: $CsoArtifactPath" } - Invoke-HakamiqCso -StepName "Deep verify CSO ($profile)" -CommandArguments $verifyArgs + Invoke-CsoKit -StepName "Deep verify CSO ($profile)" -CommandArguments $verifyArgs - Invoke-HakamiqCso -StepName "Decompress CSO to ISO ($profile)" -CommandArguments $decompressArgs + Invoke-CsoKit -StepName "Decompress CSO to ISO ($profile)" -CommandArguments $decompressArgs if (-not (Test-Path -LiteralPath $RestoredIsoPath)) { throw "Decompression completed but restored ISO was not found: $RestoredIsoPath" @@ -228,14 +206,14 @@ try { } finally { if ($success -and -not $KeepArtifacts) { - foreach ($artifact in $Artifacts) { - Remove-Item -LiteralPath $artifact -Force -ErrorAction SilentlyContinue - } - + Remove-Item -LiteralPath $WorkRoot -Recurse -Force -ErrorAction SilentlyContinue Write-Host "Artifacts removed." } - elseif (-not $success) { + elseif ($success) { + Write-Host "Artifacts kept: $WorkRoot" + } + else { Write-Host "Status: FAILED" - Write-Host "Artifacts were kept for inspection if they were created." + Write-Host "Artifacts were kept for inspection: $WorkRoot" } } diff --git a/scripts/Run-PublishedExeSmoke.ps1 b/scripts/Run-PublishedExeSmoke.ps1 index a72646d..a6b5885 100644 --- a/scripts/Run-PublishedExeSmoke.ps1 +++ b/scripts/Run-PublishedExeSmoke.ps1 @@ -15,6 +15,8 @@ param( $ErrorActionPreference = "Stop" +. (Join-Path $PSScriptRoot "OutputFileNamePolicy.ps1") + function Write-GateHeader { param( [string]$Title @@ -136,13 +138,13 @@ function Test-HelpSmoke { $text = Invoke-Exe -Arguments @( "--help" ) -ExpectedExitCodes @(0) -StepName "published help smoke" foreach ($required in @( - "hakamiq-cso info ", - "hakamiq-cso verify ", - "hakamiq-cso repair ", - "hakamiq-cso analyze ", - "hakamiq-cso detect ", - "hakamiq-cso decompress ", - "hakamiq-cso compress ", + "csokit info ", + "csokit verify ", + "csokit repair ", + "csokit analyze ", + "csokit detect ", + "csokit decompress ", + "csokit compress ", "--profile ", "[--fast]", "--threads ", @@ -250,11 +252,14 @@ function Test-PublishedRoundtripProfile { [string]$Profile ) - $csoPath = Join-Path $WorkDir ("published-$Profile.cso") - $restoredIsoPath = Join-Path $WorkDir ("published-$Profile-restored.iso") + $profileRoot = Join-Path $WorkDir $Profile + $csoPath = Join-Path $profileRoot "out.cso" + $restoredIsoPath = Join-Path $profileRoot "back.iso" + Assert-CsoKitOutputFileName -Path $csoPath -Context "Published profile CSO" + Assert-CsoKitOutputFileName -Path $restoredIsoPath -Context "Published profile restored ISO" - Remove-Item -LiteralPath $csoPath -Force -ErrorAction SilentlyContinue - Remove-Item -LiteralPath $restoredIsoPath -Force -ErrorAction SilentlyContinue + Remove-Item -LiteralPath $profileRoot -Recurse -Force -ErrorAction SilentlyContinue + New-Item -ItemType Directory -Force -Path $profileRoot | Out-Null $compressJson = Invoke-ExeJson -Arguments @( "compress", @@ -336,12 +341,14 @@ function Test-PublishedRoundtripProfile { } $RepoRoot = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")).Path -$SolutionPath = Join-Path $RepoRoot "Hakamiq.CsoKit.slnx" -$CliProject = Join-Path $RepoRoot "src\Hakamiq.Cso.Cli\Hakamiq.Cso.Cli.csproj" +$SolutionPath = Join-Path $RepoRoot "CsoKit.slnx" +$CliProject = Join-Path $RepoRoot "src\CsoKit.Cli\CsoKit.Cli.csproj" $ArtifactsRoot = Join-Path $RepoRoot "artifacts" $PublishDir = Join-Path (Join-Path $ArtifactsRoot "published-exe-smoke") $Runtime $WorkDir = Join-Path (Join-Path $ArtifactsRoot "published-exe-smoke-work") $Runtime -$ExePath = Join-Path $PublishDir "hakamiq-cso.exe" +$ExePath = Join-Path $PublishDir "csokit.exe" +$NativeDllPath = Join-Path $RepoRoot "artifacts\native-build\win-x64\Release\CsoKit.Native.dll" +$PublishNativeDllPath = Join-Path $PublishDir "CsoKit.Native.dll" if (-not (Test-Path -LiteralPath $SolutionPath)) { throw "Solution file was not found: $SolutionPath" @@ -351,6 +358,10 @@ if (-not (Test-Path -LiteralPath $CliProject)) { throw "CLI project was not found: $CliProject" } +if ($Runtime -ne "win-x64") { + throw "Published native smoke currently supports win-x64 only. Runtime requested: $Runtime" +} + $ResolvedInputIso = $null $OriginalLength = 0 $OriginalHash = $null @@ -361,7 +372,7 @@ if (-not $SkipRealIsoGates) { $OriginalHash = (Get-FileHash -LiteralPath $ResolvedInputIso -Algorithm SHA256).Hash } -Write-GateHeader -Title "Hakamiq CsoKit Published EXE Smoke" +Write-GateHeader -Title "CsoKit Published EXE Smoke" Write-Host "Repo: $RepoRoot" Write-Host "Configuration: $Configuration" Write-Host "Runtime: $Runtime" @@ -379,6 +390,14 @@ Invoke-GateStep -Name "dotnet restore" -Action { ) } +Invoke-GateStep -Name "build native backend" -Action { + & (Join-Path $PSScriptRoot "Build-Native.ps1") -Configuration Release -Platform x64 + + if (-not (Test-Path -LiteralPath $NativeDllPath -PathType Leaf)) { + throw "Native DLL was not produced: $NativeDllPath" + } +} + Invoke-GateStep -Name "dotnet publish" -Action { Remove-Item -LiteralPath $PublishDir -Recurse -Force -ErrorAction SilentlyContinue New-Item -ItemType Directory -Force -Path $PublishDir | Out-Null @@ -401,9 +420,15 @@ Invoke-GateStep -Name "dotnet publish" -Action { "-p:NuGetAudit=false" ) - if (-not (Test-Path -LiteralPath $ExePath)) { + if (-not (Test-Path -LiteralPath $ExePath -PathType Leaf)) { throw "Published executable was not found: $ExePath" } + + Copy-Item -LiteralPath $NativeDllPath -Destination $PublishNativeDllPath -Force + + if (-not (Test-Path -LiteralPath $PublishNativeDllPath -PathType Leaf)) { + throw "Published native DLL was not staged: $PublishNativeDllPath" + } } Invoke-GateStep -Name "published help smoke" -Action { diff --git a/scripts/Run-RealLocalCorpusGate.ps1 b/scripts/Run-RealLocalCorpusGate.ps1 index d3a8e00..702ea3b 100644 --- a/scripts/Run-RealLocalCorpusGate.ps1 +++ b/scripts/Run-RealLocalCorpusGate.ps1 @@ -40,8 +40,8 @@ if (-not (Test-Path -LiteralPath $resolvedRoot -PathType Container)) { } $repoRoot = Split-Path -Parent $PSScriptRoot -$exe = Join-Path $repoRoot "src/Hakamiq.Cso.Cli/bin/$Configuration/net10.0/hakamiq-cso.exe" -$dll = Join-Path $repoRoot "src/Hakamiq.Cso.Cli/bin/$Configuration/net10.0/Hakamiq.Cso.Cli.dll" +$exe = Join-Path $repoRoot "src/CsoKit.Cli/bin/$Configuration/net10.0/csokit.exe" +$dll = Join-Path $repoRoot "src/CsoKit.Cli/bin/$Configuration/net10.0/CsoKit.Cli.dll" if (Test-Path -LiteralPath $exe -PathType Leaf) { $tool = @($exe) @@ -51,7 +51,7 @@ elseif (Test-Path -LiteralPath $dll -PathType Leaf) { } else { Write-Host "CLI binary was not found. Building $Configuration first..." - & dotnet build (Join-Path $repoRoot 'Hakamiq.CsoKit.slnx') -c $Configuration + & dotnet build (Join-Path $repoRoot 'CsoKit.slnx') -c $Configuration if (Test-Path -LiteralPath $exe -PathType Leaf) { $tool = @($exe) } @@ -60,7 +60,7 @@ else { } } -$artifactRoot = Join-Path ([IO.Path]::GetTempPath()) ("HakamiqCsoKit_RealCorpus_" + [Guid]::NewGuid().ToString('N')) +$artifactRoot = Join-Path ([IO.Path]::GetTempPath()) ("CsoKit_RealCorpus_" + [Guid]::NewGuid().ToString('N')) New-Item -ItemType Directory -Path $artifactRoot | Out-Null $extensions = @('.iso', '.cso', '.zso', '.dax', '.cso2') @@ -76,7 +76,7 @@ function Invoke-CsoTool { $prefix = if ($tool.Count -gt 1) { @($tool[1..($tool.Count - 1)]) } else { @() } & $tool[0] @($prefix + $Arguments) if ($LASTEXITCODE -ne 0) { - throw "hakamiq-cso failed with exit code $LASTEXITCODE: $($Arguments -join ' ')" + throw "csokit failed with exit code $LASTEXITCODE: $($Arguments -join ' ')" } } diff --git a/scripts/Run-ReleaseGate.ps1 b/scripts/Run-ReleaseGate.ps1 index ca84d03..10cdc2f 100644 --- a/scripts/Run-ReleaseGate.ps1 +++ b/scripts/Run-ReleaseGate.ps1 @@ -131,13 +131,13 @@ function Test-HelpSmoke { } foreach ($required in @( - "hakamiq-cso info ", - "hakamiq-cso verify ", - "hakamiq-cso repair ", - "hakamiq-cso analyze ", - "hakamiq-cso detect ", - "hakamiq-cso decompress ", - "hakamiq-cso compress ", + "csokit info ", + "csokit verify ", + "csokit repair ", + "csokit analyze ", + "csokit detect ", + "csokit decompress ", + "csokit compress ", "--profile ", "[--fast]", "--threads ", @@ -202,8 +202,8 @@ function Invoke-ScriptFile { } $RepoRoot = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")).Path -$SolutionPath = Join-Path $RepoRoot "Hakamiq.CsoKit.slnx" -$CliProject = Join-Path $RepoRoot "src\Hakamiq.Cso.Cli\Hakamiq.Cso.Cli.csproj" +$SolutionPath = Join-Path $RepoRoot "CsoKit.slnx" +$CliProject = Join-Path $RepoRoot "src\CsoKit.Cli\CsoKit.Cli.csproj" $RoundtripGateScript = Join-Path $RepoRoot "scripts\Run-RoundtripGate.ps1" $ProfileMatrixScript = Join-Path $RepoRoot "scripts\Run-ProfileRoundtripMatrix.ps1" $NativeBuildScript = Join-Path $RepoRoot "scripts\Build-Native.ps1" @@ -222,7 +222,7 @@ if (-not $SkipRealIsoGates) { $ResolvedInputIso = Get-ResolvedIsoPath -Path $InputIso } -Write-GateHeader -Title "Hakamiq CsoKit Release Gate" +Write-GateHeader -Title "CsoKit Release Gate" Write-Host "Repo: $RepoRoot" Write-Host "Configuration: $Configuration" Write-Host "Real ISO: $(if ($SkipRealIsoGates) { 'skipped' } else { $ResolvedInputIso })" diff --git a/scripts/Run-RoundtripGate.ps1 b/scripts/Run-RoundtripGate.ps1 index 34ea363..0f59e0a 100644 --- a/scripts/Run-RoundtripGate.ps1 +++ b/scripts/Run-RoundtripGate.ps1 @@ -10,6 +10,8 @@ param( $ErrorActionPreference = "Stop" +. (Join-Path $PSScriptRoot "OutputFileNamePolicy.ps1") + function Get-ResolvedFilePath { param( [string]$Path, @@ -35,32 +37,7 @@ function Get-ResolvedFilePath { return $item.FullName } -function New-UniqueSiblingPath { - param( - [string]$DirectoryPath, - [string]$BaseName, - [string]$Suffix, - [string]$Extension - ) - - $candidate = Join-Path $DirectoryPath ("{0}{1}{2}" -f $BaseName, $Suffix, $Extension) - - if (-not (Test-Path -LiteralPath $candidate)) { - return $candidate - } - - for ($index = 2; $index -lt 10000; $index++) { - $candidate = Join-Path $DirectoryPath ("{0}{1} {2}{3}" -f $BaseName, $Suffix, $index, $Extension) - - if (-not (Test-Path -LiteralPath $candidate)) { - return $candidate - } - } - - throw "Could not find a free artifact name in: $DirectoryPath" -} - -function Invoke-HakamiqCso { +function Invoke-CsoKit { param( [string]$StepName, [string[]]$CommandArguments @@ -93,7 +70,7 @@ function Get-Sha256Hex { } $RepoRoot = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")).Path -$CliProject = Join-Path $RepoRoot "src\Hakamiq.Cso.Cli\Hakamiq.Cso.Cli.csproj" +$CliProject = Join-Path $RepoRoot "src\CsoKit.Cli\CsoKit.Cli.csproj" if (-not (Test-Path -LiteralPath $CliProject)) { throw "CLI project was not found: $CliProject" @@ -107,9 +84,11 @@ if (-not [string]::Equals($InputItem.Extension, ".iso", [System.StringComparison } $DirectoryPath = $InputItem.DirectoryName -$BaseName = [System.IO.Path]::GetFileNameWithoutExtension($InputItem.Name) -$CsoArtifactPath = New-UniqueSiblingPath -DirectoryPath $DirectoryPath -BaseName $BaseName -Suffix " - Hakamiq Roundtrip Gate" -Extension ".cso" -$RestoredIsoPath = New-UniqueSiblingPath -DirectoryPath $DirectoryPath -BaseName $BaseName -Suffix " - Hakamiq Roundtrip Restored" -Extension ".iso" +$WorkRoot = Join-Path $DirectoryPath (".csokit-roundtrip-" + [System.Guid]::NewGuid().ToString("N")) +$CsoArtifactPath = Join-Path $WorkRoot "out.cso" +$RestoredIsoPath = Join-Path $WorkRoot "back.iso" +Assert-CsoKitOutputFileName -Path $CsoArtifactPath -Context "Round-trip gate CSO" +Assert-CsoKitOutputFileName -Path $RestoredIsoPath -Context "Round-trip gate restored ISO" $compressArgs = @("compress", $InputIsoPath, "-o", $CsoArtifactPath) $verifyArgs = @("verify", $CsoArtifactPath, "--deep", "--sha256") @@ -120,7 +99,7 @@ if ($Quiet) { $decompressArgs += "--quiet" } -Write-Host "Hakamiq CsoKit Roundtrip Gate" +Write-Host "CsoKit Roundtrip Gate" Write-Host "Input: $InputIsoPath" Write-Host "CSO output: $CsoArtifactPath" Write-Host "ISO output: $RestoredIsoPath" @@ -129,17 +108,18 @@ Write-Host "Artifacts: $(if ($KeepArtifacts) { 'kept' } else { 'deleted on suc $success = $false try { + New-Item -ItemType Directory -Force -Path $WorkRoot | Out-Null $originalHash = Get-Sha256Hex -Path $InputIsoPath - Invoke-HakamiqCso -StepName "Compress ISO to CSO" -CommandArguments $compressArgs + Invoke-CsoKit -StepName "Compress ISO to CSO" -CommandArguments $compressArgs if (-not (Test-Path -LiteralPath $CsoArtifactPath)) { throw "Compression completed but CSO artifact was not found: $CsoArtifactPath" } - Invoke-HakamiqCso -StepName "Deep verify CSO" -CommandArguments $verifyArgs + Invoke-CsoKit -StepName "Deep verify CSO" -CommandArguments $verifyArgs - Invoke-HakamiqCso -StepName "Decompress CSO to ISO" -CommandArguments $decompressArgs + Invoke-CsoKit -StepName "Decompress CSO to ISO" -CommandArguments $decompressArgs if (-not (Test-Path -LiteralPath $RestoredIsoPath)) { throw "Decompression completed but restored ISO was not found: $RestoredIsoPath" @@ -173,12 +153,14 @@ try { } finally { if ($success -and -not $KeepArtifacts) { - Remove-Item -LiteralPath $CsoArtifactPath -Force -ErrorAction SilentlyContinue - Remove-Item -LiteralPath $RestoredIsoPath -Force -ErrorAction SilentlyContinue + Remove-Item -LiteralPath $WorkRoot -Recurse -Force -ErrorAction SilentlyContinue Write-Host "Artifacts removed." } - elseif (-not $success) { + elseif ($success) { + Write-Host "Artifacts kept: $WorkRoot" + } + else { Write-Host "Status: FAILED" - Write-Host "Artifacts were kept for inspection if they were created." + Write-Host "Artifacts were kept for inspection: $WorkRoot" } } diff --git a/scripts/Verify-Hardening.ps1 b/scripts/Verify-Hardening.ps1 new file mode 100644 index 0000000..a79c031 --- /dev/null +++ b/scripts/Verify-Hardening.ps1 @@ -0,0 +1,193 @@ +[CmdletBinding()] +param( + [ValidateSet("Debug", "Release")] + [string]$Configuration = "Release", + [string]$Runtime = "win-x64" +) + +$ErrorActionPreference = "Stop" +$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path +$Solution = Join-Path $RepoRoot "CsoKit.slnx" +$NativeDll = Join-Path $RepoRoot "artifacts\native-build\win-x64\Release\CsoKit.Native.dll" +$TestOutput = Join-Path $RepoRoot "tests\CsoKit.Tests\bin\$Configuration\net10.0\CsoKit.Native.dll" + +function Invoke-Checked { + param([string]$Name, [scriptblock]$Command) + Write-Host "[RUN] $Name" + & $Command + if ($LASTEXITCODE -ne 0) { + throw "$Name failed with exit code $LASTEXITCODE." + } +} + +if (-not (Test-Path -LiteralPath $Solution -PathType Leaf)) { + throw "Solution was not found: $Solution" +} + + +Write-Host "[RUN] Architecture source guards" +$CliProject = Join-Path $RepoRoot "src\CsoKit.Cli\CsoKit.Cli.csproj" +$CliSourceRoot = Join-Path $RepoRoot "src\CsoKit.Cli" +$ApplicationSourceRoot = Join-Path $RepoRoot "src\CsoKit.Application" + +$cliProjectText = Get-Content -LiteralPath $CliProject -Raw +if ($cliProjectText -match 'ProjectReference[^>]+CsoKit\.Core') { + throw "CLI must reference CsoKit.Application instead of CsoKit.Core directly." +} + +$forbiddenCliUseCasePatterns = @( + 'new\s+CsoCompressor\s*\(', + 'new\s+CsoRepairer\s*\(', + 'new\s+CsoVerifier\s*\(', + 'new\s+CsoDeepVerifier\s*\(', + 'ContainerDeepVerifier\.Verify\s*\(' +) + +$cliSourceText = (Get-ChildItem -LiteralPath $CliSourceRoot -Filter *.cs -Recurse -File | + ForEach-Object { Get-Content -LiteralPath $_.FullName -Raw }) -join "`n" + +foreach ($pattern in $forbiddenCliUseCasePatterns) { + if ($cliSourceText -match $pattern) { + throw "CLI bypasses CsoKit.Application with forbidden use-case pattern: $pattern" + } +} + +$legacyDetailParser = Join-Path $ApplicationSourceRoot "CsoOperationDetailParser.cs" +if (Test-Path -LiteralPath $legacyDetailParser) { + throw "Legacy text detail parser must not exist: $legacyDetailParser" +} + +$applicationSourceText = (Get-ChildItem -LiteralPath $ApplicationSourceRoot -Filter *.cs -Recurse -File | + ForEach-Object { Get-Content -LiteralPath $_.FullName -Raw }) -join "`n" +if ($applicationSourceText -match 'CsoOperationDetailParser') { + throw "Application results must originate from typed detail records, not parsed report text." +} + +Write-Host "[PASS] Architecture source guards" + + +Write-Host "[RUN] Release script output-name guards" +$OutputFileNamePolicy = Join-Path $PSScriptRoot "OutputFileNamePolicy.ps1" +if (-not (Test-Path -LiteralPath $OutputFileNamePolicy -PathType Leaf)) { + throw "Output filename policy helper was not found: $OutputFileNamePolicy" +} + +. $OutputFileNamePolicy + +foreach ($validName in @("ab.cso", "1234567890.iso", "éx.cso")) { + Assert-CsoKitOutputFileName -Path $validName -Context "Output filename policy self-test" +} + +foreach ($invalidName in @(("x" + ".cso"), ("1234567890" + "1" + ".iso"))) { + $wasRejected = $false + + try { + Assert-CsoKitOutputFileName -Path $invalidName -Context "Output filename policy negative self-test" + } + catch { + $wasRejected = $true + } + + if (-not $wasRejected) { + throw "Output filename policy accepted an invalid self-test name: $invalidName" + } +} + +$guardedReleaseScripts = @( + "Publish-Release.ps1", + "Run-PublishedExeSmoke.ps1", + "Run-RoundtripGate.ps1", + "Run-ProfileRoundtripMatrix.ps1" +) + +foreach ($scriptName in $guardedReleaseScripts) { + $scriptPath = Join-Path $PSScriptRoot $scriptName + $scriptText = Get-Content -LiteralPath $scriptPath -Raw + + if ($scriptText -notmatch 'OutputFileNamePolicy\.ps1') { + throw "Release script does not load the output filename guard: $scriptName" + } + + if ($scriptText -notmatch 'Assert-CsoKitOutputFileName') { + throw "Release script does not validate generated output names: $scriptName" + } +} + +$quotedOutputPattern = '["''](?[^"'']+\.(?:cso|iso))["'']' +Get-ChildItem -LiteralPath $PSScriptRoot -Filter *.ps1 -File | ForEach-Object { + $scriptPath = $_.FullName + $scriptText = Get-Content -LiteralPath $scriptPath -Raw + + foreach ($match in [regex]::Matches($scriptText, $quotedOutputPattern, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)) { + $literalPath = $match.Groups['path'].Value + + if ($literalPath.Contains('$')) { + continue + } + + Assert-CsoKitOutputFileName -Path $literalPath -Context "PowerShell literal in $($_.Name)" + } +} + +Write-Host "[PASS] Release script output-name guards" + +Write-Host "[RUN] Published EXE smoke source guards" +$PublishedSmokePath = Join-Path $PSScriptRoot "Run-PublishedExeSmoke.ps1" +$publishedSmokeText = Get-Content -LiteralPath $PublishedSmokePath -Raw + +foreach ($requiredSmokePattern in @( + 'csokit verify ', + 'Build-Native\.ps1', + 'CsoKit\.Native\.dll', + 'Copy-Item\s+-LiteralPath\s+\$NativeDllPath\s+-Destination\s+\$PublishNativeDllPath' +)) { + if ($publishedSmokeText -notmatch $requiredSmokePattern) { + throw "Published EXE smoke is missing required contract or native staging pattern: $requiredSmokePattern" + } +} + +$verifyScriptText = Get-Content -LiteralPath $PSCommandPath -Raw +if ($verifyScriptText -notmatch 'Run-PublishedExeSmoke\.ps1') { + throw "Verify-Hardening must execute Run-PublishedExeSmoke.ps1." +} + +Write-Host "[PASS] Published EXE smoke source guards" + + +Invoke-Checked "Restore" { + dotnet restore $Solution -r $Runtime -p:NuGetAudit=false +} + +Write-Host "[RUN] Build native backend" +& (Join-Path $PSScriptRoot "Build-Native.ps1") -Configuration Release -Platform x64 +if (-not (Test-Path -LiteralPath $NativeDll -PathType Leaf)) { + throw "Native DLL was not produced: $NativeDll" +} + +Invoke-Checked "Build Debug" { + dotnet build $Solution -c Debug --no-restore -p:NuGetAudit=false +} + +Invoke-Checked "Build Release" { + dotnet build $Solution -c Release --no-restore -p:NuGetAudit=false +} + +New-Item -ItemType Directory -Force (Split-Path -Parent $TestOutput) | Out-Null +Copy-Item -LiteralPath $NativeDll -Destination $TestOutput -Force + +Invoke-Checked "Tests with native integration" { + dotnet test $Solution -c $Configuration --no-build +} + +Write-Host "[RUN] Published EXE smoke" +& (Join-Path $PSScriptRoot "Run-PublishedExeSmoke.ps1") ` + -Configuration $Configuration ` + -Runtime $Runtime ` + -SkipRealIsoGates ` + -Quiet + +Write-Host "[RUN] Publish and verify release" +& (Join-Path $PSScriptRoot "Publish-Release.ps1") -Runtime $Runtime +& (Join-Path $PSScriptRoot "Verify-Release.ps1") -Runtime $Runtime + +Write-Host "[PASS] CsoKit hardening verification completed." diff --git a/scripts/Verify-Release.ps1 b/scripts/Verify-Release.ps1 index 57292e2..30fbde0 100644 --- a/scripts/Verify-Release.ps1 +++ b/scripts/Verify-Release.ps1 @@ -1,6 +1,6 @@ [CmdletBinding()] param( - [string]$Version = "0.6.0", + [string]$Version = "", [string]$Runtime = "win-x64" ) @@ -61,18 +61,25 @@ function Test-BlockedArtifacts { } $RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path +$versionFile = Join-Path $RepoRoot "VERSION" +if ([string]::IsNullOrWhiteSpace($Version)) { + $Version = (Get-Content -LiteralPath $versionFile -Raw).Trim() +} +if ([string]::IsNullOrWhiteSpace($Version)) { + throw "VERSION is empty." +} $ArtifactsDir = Join-Path $RepoRoot "artifacts" $PublishDir = Join-Path (Join-Path $ArtifactsDir "publish") $Runtime $ReleaseDir = Join-Path $ArtifactsDir "release" -$ExePath = Join-Path $PublishDir "hakamiq-cso.exe" -$NativeDllPath = Join-Path $PublishDir "Hakamiq.Cso.Native.dll" +$ExePath = Join-Path $PublishDir "csokit.exe" +$NativeDllPath = Join-Path $PublishDir "CsoKit.Native.dll" $ReleaseNotesPath = Join-Path $PublishDir "RELEASE_NOTES.md" $ThirdPartyNoticesPath = Join-Path $PublishDir "THIRD_PARTY_NOTICES.md" $ManifestPath = Join-Path $PublishDir "SHA256SUMS.txt" -$ZipPath = Join-Path $ReleaseDir "hakamiq-csokit-$Version-$Runtime.zip" +$ZipPath = Join-Path $ReleaseDir "csokit-$Version-$Runtime.zip" $ZipCheckDir = Join-Path $ArtifactsDir "verify-release-check" -Write-Host "Hakamiq CsoKit Release Verifier" +Write-Host "CsoKit Release Verifier" Write-Host "Version: $Version" Write-Host "Runtime: $Runtime" Write-Host "" @@ -143,7 +150,7 @@ if ($manifestLines.Count -lt 4) { $manifestText = $manifestLines | Out-String -foreach ($requiredFile in @("hakamiq-cso.exe", "Hakamiq.Cso.Native.dll", "README.md", "LICENSE.txt", "RELEASE_NOTES.md", "THIRD_PARTY_NOTICES.md")) { +foreach ($requiredFile in @("csokit.exe", "CsoKit.Native.dll", "README.md", "LICENSE.txt", "RELEASE_NOTES.md", "THIRD_PARTY_NOTICES.md")) { if ($manifestText -notmatch [regex]::Escape($requiredFile)) { throw "SHA256 manifest does not contain required file: $requiredFile" } @@ -155,8 +162,8 @@ New-Item -ItemType Directory -Force $ZipCheckDir | Out-Null try { Expand-Archive -Path $ZipPath -DestinationPath $ZipCheckDir -Force - $ZipExePath = Join-Path $ZipCheckDir "hakamiq-cso.exe" - $ZipNativeDllPath = Join-Path $ZipCheckDir "Hakamiq.Cso.Native.dll" + $ZipExePath = Join-Path $ZipCheckDir "csokit.exe" + $ZipNativeDllPath = Join-Path $ZipCheckDir "CsoKit.Native.dll" $ZipManifestPath = Join-Path $ZipCheckDir "SHA256SUMS.txt" $ZipReleaseNotesPath = Join-Path $ZipCheckDir "RELEASE_NOTES.md" $ZipThirdPartyNoticesPath = Join-Path $ZipCheckDir "THIRD_PARTY_NOTICES.md" @@ -185,7 +192,7 @@ try { $zipManifestText = Get-Content $ZipManifestPath | Out-String - foreach ($requiredFile in @("hakamiq-cso.exe", "Hakamiq.Cso.Native.dll", "README.md", "LICENSE.txt", "RELEASE_NOTES.md", "THIRD_PARTY_NOTICES.md")) { + foreach ($requiredFile in @("csokit.exe", "CsoKit.Native.dll", "README.md", "LICENSE.txt", "RELEASE_NOTES.md", "THIRD_PARTY_NOTICES.md")) { if ($zipManifestText -notmatch [regex]::Escape($requiredFile)) { throw "ZIP SHA256 manifest does not contain required file: $requiredFile" } diff --git a/src/Hakamiq.Cso.App/App.xaml b/src/CsoKit.App/App.xaml similarity index 85% rename from src/Hakamiq.Cso.App/App.xaml rename to src/CsoKit.App/App.xaml index d8ccead..49286a5 100644 --- a/src/Hakamiq.Cso.App/App.xaml +++ b/src/CsoKit.App/App.xaml @@ -1,4 +1,4 @@ - diff --git a/src/CsoKit.App/App.xaml.cs b/src/CsoKit.App/App.xaml.cs new file mode 100644 index 0000000..f84705a --- /dev/null +++ b/src/CsoKit.App/App.xaml.cs @@ -0,0 +1,7 @@ +using System.Windows; + +namespace CsoKit.App; + +public partial class App : System.Windows.Application +{ +} diff --git a/src/Hakamiq.Cso.App/Assets/Icons/advanced_key.png b/src/CsoKit.App/Assets/Icons/advanced_key.png similarity index 100% rename from src/Hakamiq.Cso.App/Assets/Icons/advanced_key.png rename to src/CsoKit.App/Assets/Icons/advanced_key.png diff --git a/src/Hakamiq.Cso.App/Assets/Icons/hakamiq.ico b/src/CsoKit.App/Assets/Icons/csokit.ico similarity index 100% rename from src/Hakamiq.Cso.App/Assets/Icons/hakamiq.ico rename to src/CsoKit.App/Assets/Icons/csokit.ico diff --git a/src/Hakamiq.Cso.App/Assets/Icons/hakamiq_32.png b/src/CsoKit.App/Assets/Icons/csokit_32.png similarity index 100% rename from src/Hakamiq.Cso.App/Assets/Icons/hakamiq_32.png rename to src/CsoKit.App/Assets/Icons/csokit_32.png diff --git a/src/Hakamiq.Cso.App/Assets/Icons/status_error.png b/src/CsoKit.App/Assets/Icons/status_error.png similarity index 100% rename from src/Hakamiq.Cso.App/Assets/Icons/status_error.png rename to src/CsoKit.App/Assets/Icons/status_error.png diff --git a/src/Hakamiq.Cso.App/Assets/Icons/status_success.png b/src/CsoKit.App/Assets/Icons/status_success.png similarity index 100% rename from src/Hakamiq.Cso.App/Assets/Icons/status_success.png rename to src/CsoKit.App/Assets/Icons/status_success.png diff --git a/src/Hakamiq.Cso.App/Hakamiq.Cso.App.csproj b/src/CsoKit.App/CsoKit.App.csproj similarity index 57% rename from src/Hakamiq.Cso.App/Hakamiq.Cso.App.csproj rename to src/CsoKit.App/CsoKit.App.csproj index 82179eb..487969e 100644 --- a/src/Hakamiq.Cso.App/Hakamiq.Cso.App.csproj +++ b/src/CsoKit.App/CsoKit.App.csproj @@ -8,34 +8,31 @@ enable true - Hakamiq.Cso.App - Hakamiq.Cso.App - - 0.6.0 - 0.6.0 - 0.6.0 + CsoKit.App + CsoKit.App HAKAMIQ HAKAMIQ - Hakamiq CsoKit App + CsoKit App win-x64 - Assets\Icons\hakamiq.ico + Assets\Icons\csokit.ico - + + - - + + - - + + diff --git a/src/Hakamiq.Cso.App/Localization/ArabicUiText.cs b/src/CsoKit.App/Localization/ArabicUiText.cs similarity index 95% rename from src/Hakamiq.Cso.App/Localization/ArabicUiText.cs rename to src/CsoKit.App/Localization/ArabicUiText.cs index 6dbcd87..fc96846 100644 --- a/src/Hakamiq.Cso.App/Localization/ArabicUiText.cs +++ b/src/CsoKit.App/Localization/ArabicUiText.cs @@ -1,6 +1,6 @@ using System.Windows; -namespace Hakamiq.Cso.App.Localization; +namespace CsoKit.App.Localization; public enum UiLanguage { @@ -240,6 +240,8 @@ public sealed class UiText public required string InvalidThreads { get; init; } + public required string InvalidOutputFileNameLength { get; init; } + public required string UnsupportedOperation { get; init; } public required string OperationDoesNotUseOutput { get; init; } @@ -253,8 +255,8 @@ public static class ArabicUiText { Language = UiLanguage.Arabic, FlowDirection = FlowDirection.RightToLeft, - WindowTitle = "Hakamiq CsoKit", - AppTitle = "Hakamiq CsoKit", + WindowTitle = "CsoKit", + AppTitle = "CsoKit", AppSubtitle = "محول صور ألعاب PSP: ضغط، فك ضغط، فحص، تحليل، وإصلاح.", EngineStatus = "متصل مباشرة بالمحرك الأساسي", LanguageToggleToolTip = "تبديل اللغة بين العربية والإنجليزية", @@ -263,7 +265,7 @@ public static class ArabicUiText InputFile = "ملف المصدر", InputFileHint = "اختر ملف ISO أو CSO أو ZSO أو DAX، أو اسحبه إلى هذه المنطقة.", OutputFile = "ملف الإخراج", - OutputFileHint = "يتم اقتراح مسار الإخراج تلقائياً حسب العملية.", + OutputFileHint = "يتم اقتراح مسار الإخراج تلقائياً واسم الملف من حرفين إلى 10 أحرف بدون الامتداد.", BrowseInput = "اختيار ملفات", BrowseFolder = "اختيار مجلد", BrowseOutput = "حفظ باسم", @@ -362,7 +364,7 @@ public static class ArabicUiText ResultSize = "الحجم الناتج", SavedSize = "الموفر", - Footer = "واجهة WPF تستدعي Hakamiq.Cso.Core مباشرة دون تشغيل CLI كعملية منفصلة.", + Footer = "واجهة WPF تستدعي CsoKit.Core مباشرة دون تشغيل CLI كعملية منفصلة.", SelectInputFile = "اختيار ملف المصدر", SelectOutputFile = "تحديد ملف الإخراج", @@ -373,6 +375,7 @@ public static class ArabicUiText InvalidCompressionProfile = "نمط الضغط المحدد غير صحيح.", InvalidBlockSize = "حجم الكتلة يجب أن يكون رقماً صحيحاً أكبر من الصفر.", InvalidThreads = "عدد العمليات المتزامنة يجب أن يكون رقماً صحيحاً أكبر من الصفر.", + InvalidOutputFileNameLength = "اسم ملف الإخراج يجب ألا يقل عن حرفين وألا يزيد على 10 أحرف بدون الامتداد.", UnsupportedOperation = "هذه العملية غير مدعومة حالياً.", OperationDoesNotUseOutput = "هذه العملية لا تتطلب ملف إخراج.", OutputPathNotRequired = "مسار الإخراج غير مطلوب لهذه العملية.", @@ -382,8 +385,8 @@ public static class ArabicUiText { Language = UiLanguage.English, FlowDirection = FlowDirection.LeftToRight, - WindowTitle = "Hakamiq CsoKit", - AppTitle = "Hakamiq CsoKit", + WindowTitle = "CsoKit", + AppTitle = "CsoKit", AppSubtitle = "PSP image converter: compress, decompress, verify, analyze, and repair.", EngineStatus = "Connected directly to the core engine", LanguageToggleToolTip = "Switch language between Arabic and English", @@ -392,7 +395,7 @@ public static class ArabicUiText InputFile = "Source file", InputFileHint = "Choose an ISO, CSO, ZSO, or DAX file, or drop it into this area.", OutputFile = "Output file", - OutputFileHint = "The output path is suggested automatically based on the selected operation.", + OutputFileHint = "The output path is suggested automatically; the file name must be 2 to 10 characters excluding the extension.", BrowseInput = "Choose files", BrowseFolder = "Choose folder", BrowseOutput = "Save as", @@ -491,7 +494,7 @@ public static class ArabicUiText ResultSize = "Result size", SavedSize = "Saved", - Footer = "WPF interface calling Hakamiq.Cso.Core directly without launching the CLI as a separate process.", + Footer = "WPF interface calling CsoKit.Core directly without launching the CLI as a separate process.", SelectInputFile = "Select source file", SelectOutputFile = "Select output file", @@ -502,6 +505,7 @@ public static class ArabicUiText InvalidCompressionProfile = "The selected compression profile is invalid.", InvalidBlockSize = "Block size must be a positive integer.", InvalidThreads = "Parallel operations must be a positive integer.", + InvalidOutputFileNameLength = "The output file name must be between 2 and 10 characters, excluding the extension.", UnsupportedOperation = "This operation is not supported.", OperationDoesNotUseOutput = "This operation does not require an output file.", OutputPathNotRequired = "An output path is not required for this operation.", diff --git a/src/Hakamiq.Cso.App/MainWindow.xaml b/src/CsoKit.App/MainWindow.xaml similarity index 99% rename from src/Hakamiq.Cso.App/MainWindow.xaml rename to src/CsoKit.App/MainWindow.xaml index f11ab52..ef5b259 100644 --- a/src/Hakamiq.Cso.App/MainWindow.xaml +++ b/src/CsoKit.App/MainWindow.xaml @@ -1,8 +1,8 @@ - + IsEnabled="{Binding CanCancel, Mode=OneWay}" + Click="StopOperationButton_Click" />