From 551f14cd86c466348b75c2938828bcd0e202afef Mon Sep 17 00:00:00 2001 From: gamer147 Date: Tue, 18 Aug 2026 08:39:15 -0400 Subject: [PATCH] Rename release outputs and managed project to OME --- .gitea/workflows/linux-release-build.yml | 28 +++++----- docs/PROJECT-STRUCTURE.md | 6 +-- docs/phase-b-framework.md | 2 +- docs/platform-portability.md | 16 +++--- docs/tools-reference.md | 25 ++++----- .../Properties/AssemblyInfo.cs | 2 +- godot/Main.PackageSmoke.cs | 2 +- godot/Main.SelfTest.cs | 2 +- godot/Main.cs | 2 +- godot/{Himegari.csproj => OME.csproj} | 2 +- godot/{Himegari.sln => OME.sln} | 2 +- ...ntimeMetadata.cs => OmeRuntimeMetadata.cs} | 8 +-- godot/export_presets.cfg | 4 +- godot/project.godot | 2 +- run-godot.ps1 | 2 +- tools/build-linux-x64.sh | 16 +++--- tools/build-windows-x64.sh | 14 ++--- tools/export-linux-x64.ps1 | 4 +- tools/package_linux_x64.py | 18 ++++--- tools/package_windows_x64.py | 22 ++++---- tools/publish_gitea_release.py | 18 +++---- tools/test_dotnet_publish_proxy.py | 20 ++++---- tools/test_package_linux_x64.py | 24 +++++++-- tools/test_package_windows_x64.py | 24 +++++++-- tools/test_publish_gitea_release.py | 9 ++-- tools/test_release_workflow.py | 51 +++++++++++++++++-- tools/validate.py | 2 +- 27 files changed, 209 insertions(+), 118 deletions(-) rename godot/{Himegari.csproj => OME.csproj} (97%) rename godot/{Himegari.sln => OME.sln} (93%) rename godot/{HimegariRuntimeMetadata.cs => OmeRuntimeMetadata.cs} (67%) diff --git a/.gitea/workflows/linux-release-build.yml b/.gitea/workflows/linux-release-build.yml index 48527b8..086f2ae 100644 --- a/.gitea/workflows/linux-release-build.yml +++ b/.gitea/workflows/linux-release-build.yml @@ -69,17 +69,17 @@ jobs: - name: Stage verified workflow artifact run: | mkdir -p build/workflow-artifact - cp build/package/OpenMaidEngine-Himegari-linux-x64.tar.gz build/workflow-artifact/ - cp build/package/staging/OpenMaidEngine-Himegari-linux-x64/BUILD-INFO.json build/workflow-artifact/ - cp build/package/staging/OpenMaidEngine-Himegari-linux-x64/SHA256SUMS build/workflow-artifact/ + cp build/package/OME-linux-x64.tar.gz build/workflow-artifact/ + cp build/package/staging/OME-linux-x64/BUILD-INFO.json build/workflow-artifact/ + cp build/package/staging/OME-linux-x64/SHA256SUMS build/workflow-artifact/ cp build/package/package-smoke.log build/workflow-artifact/ cd build/workflow-artifact - sha256sum OpenMaidEngine-Himegari-linux-x64.tar.gz > OpenMaidEngine-Himegari-linux-x64.tar.gz.sha256 + sha256sum OME-linux-x64.tar.gz > OME-linux-x64.tar.gz.sha256 - name: Upload verified Linux package uses: christopherhx/gitea-upload-artifact@v4 with: - name: OpenMaidEngine-Himegari-linux-x64-${{ gitea.sha }} + name: OME-linux-x64-${{ gitea.sha }} path: build/workflow-artifact/* if-no-files-found: error retention-days: 30 @@ -155,17 +155,17 @@ jobs: - name: Stage verified workflow artifact run: | mkdir -p build/workflow-artifact-windows - cp build/package/windows-x64/OpenMaidEngine-Himegari-windows-x64.zip build/workflow-artifact-windows/ - cp build/package/windows-x64/staging/OpenMaidEngine-Himegari-windows-x64/BUILD-INFO.json build/workflow-artifact-windows/ - cp build/package/windows-x64/staging/OpenMaidEngine-Himegari-windows-x64/SHA256SUMS build/workflow-artifact-windows/ - cp build/package/windows-x64/staging/OpenMaidEngine-Himegari-windows-x64/WINDOWS-VERIFICATION.json build/workflow-artifact-windows/ + cp build/package/windows-x64/OME-windows-x64.zip build/workflow-artifact-windows/ + cp build/package/windows-x64/staging/OME-windows-x64/BUILD-INFO.json build/workflow-artifact-windows/ + cp build/package/windows-x64/staging/OME-windows-x64/SHA256SUMS build/workflow-artifact-windows/ + cp build/package/windows-x64/staging/OME-windows-x64/WINDOWS-VERIFICATION.json build/workflow-artifact-windows/ cd build/workflow-artifact-windows - sha256sum OpenMaidEngine-Himegari-windows-x64.zip > OpenMaidEngine-Himegari-windows-x64.zip.sha256 + sha256sum OME-windows-x64.zip > OME-windows-x64.zip.sha256 - name: Upload verified Windows package uses: christopherhx/gitea-upload-artifact@v4 with: - name: OpenMaidEngine-Himegari-windows-x64-${{ gitea.sha }} + name: OME-windows-x64-${{ gitea.sha }} path: build/workflow-artifact-windows/* if-no-files-found: error retention-days: 30 @@ -177,7 +177,7 @@ jobs: name: windows-release-failure-${{ gitea.run_id }}-${{ gitea.run_attempt }} path: | build/native/win-x64/verification.json - build/package/windows-x64/staging/OpenMaidEngine-Himegari-windows-x64/WINDOWS-VERIFICATION.json + build/package/windows-x64/staging/OME-windows-x64/WINDOWS-VERIFICATION.json build/validation/** if-no-files-found: ignore retention-days: 7 @@ -209,13 +209,13 @@ jobs: - name: Download verified Linux artifact uses: christopherhx/gitea-download-artifact@v4 with: - name: OpenMaidEngine-Himegari-linux-x64-${{ gitea.sha }} + name: OME-linux-x64-${{ gitea.sha }} path: build/release-assets/linux - name: Download verified Windows artifact uses: christopherhx/gitea-download-artifact@v4 with: - name: OpenMaidEngine-Himegari-windows-x64-${{ gitea.sha }} + name: OME-windows-x64-${{ gitea.sha }} path: build/release-assets/windows - name: Create or resume Gitea release diff --git a/docs/PROJECT-STRUCTURE.md b/docs/PROJECT-STRUCTURE.md index 2e27d55..feef36c 100644 --- a/docs/PROJECT-STRUCTURE.md +++ b/docs/PROJECT-STRUCTURE.md @@ -158,13 +158,13 @@ S:\Game Hacking\Eushully\Himegari\ ← workspace root (three siblings) ├── tools/frida/ runtime-capture + engine-dump scripts (see tools/frida/README.md) └── godot/ DELIVERABLE — the Godot/C# ADV front-end (references Age.Engine plus the optional exact Windows text adapter). Its assembly embeds - generated build/opcodes.json through HimegariRuntimeMetadata, so + generated build/opcodes.json through OmeRuntimeMetadata, so exports do not need repository discovery. Also contains the portable TextServer glyph adapter, per-profile font-substitution configuration, and TITLE-only F4 debug scene launcher ``` -The Godot deliverable includes `Himegari.sln` because Godot's .NET exporter requires a solution, +The Godot deliverable includes `OME.sln` because Godot's .NET exporter requires a solution, `export_presets.cfg` for Linux and Windows x86_64, and `build/.gdignore` so disposable capture frames below the project do not enter its import or export scan. `tools/build-linux-x64.sh` and `tools/build-windows-x64.sh` produce their complete disposable artifacts under `build/export/`; the older @@ -181,7 +181,7 @@ Godot input routing, locator/debug hotkeys, debug-scene dispatch, cursor control full-width text entry. `engine/Age.Engine.Frontend/` is the production owner of frontend helpers that do not depend on Godot types. -Both `engine/AgeEngine.sln` and `godot/Himegari.sln` include the project; Godot and `Age.Engine.Tests` consume it +Both `engine/AgeEngine.sln` and `godot/OME.sln` include the project; Godot and `Age.Engine.Tests` consume it through project references rather than compiling duplicate linked sources. The first owned cluster contains `PageLocatorState`, `GodotTimelineLog`, `GodotTraceSink`, `StepLimitDiagnosticFormatter`, `GodotVmOptions`, `PerformanceFrameLog`, and `WindowLaunchOptions`. It also owns the internal movie decoder boundary/runtime, diff --git a/docs/phase-b-framework.md b/docs/phase-b-framework.md index 0ddf73c..3dfdb68 100644 --- a/docs/phase-b-framework.md +++ b/docs/phase-b-framework.md @@ -758,7 +758,7 @@ decodes at most one frame ahead, waits against a monotonic `Stopwatch` clock for newest-frame-wins handoff, and reports EOF only after the larger of declared stop time or the final frame interval. Disposal interrupts a far-future frame wait and joins the worker; asynchronous decode failure records a diagnostic and completes the decoder so AGE cannot remain blocked. `Main` now selects `FfmpegMovieDecoderFactory`, while the -Godot build stages the shim and its five local shared-library dependencies beside `Himegari.dll`. DirectShow stays +Godot build stages the shim and its five local shared-library dependencies beside `OME.dll`. DirectShow stays in-tree but is no longer selected; delete it only after the corpus and live acceptance gates. Deterministic fake- clock tests cover due-frame publication, final completion, cancellation, and failure. Real paced probes cover formerly failing 280x352 `MVB961` and aligned `MVB908`. A natural headless SYSTEM4 smoke played and released diff --git a/docs/platform-portability.md b/docs/platform-portability.md index ae2d7fe..0a395e7 100644 --- a/docs/platform-portability.md +++ b/docs/platform-portability.md @@ -149,7 +149,7 @@ both external archive hashes, exact clean tag-commit metadata and target RID, ma ledgers inside each archive, Linux's accepted dynamic package smoke, and Windows's complete static AMD64/ABI/ import report. It creates or resumes only a matching release, rejects unexpected or colliding assets, and exposes exactly two distributable archives: -`OpenMaidEngine-Himegari-linux-x64.tar.gz` and `OpenMaidEngine-Himegari-windows-x64.zip`. A third small +`OME-linux-x64.tar.gz` and `OME-windows-x64.zip`. A third small `RELEASE-SHA256SUMS` attachment will authenticate both archives while keeping the release below Gitea's observed five-attachment boundary; detailed build metadata, payload ledgers, and logs remain inside each archive and in the retained workflow artifacts. The release notes will state that Linux received the dynamic package smoke and @@ -158,8 +158,10 @@ pass. The hosted develop run at `d657c63` completed both platform builds and cor 2026-08-03, accepting the paired non-tag path. Its core job initially failed before checkout on a transient runner DNS lookup for GitHub, then passed unchanged on retry; this was infrastructure availability rather than a validation failure. The lightweight `v0.2.0` tag at `93d8236` then completed both platform jobs and promotion on -2026-08-03. The resulting Gitea release exposes exactly the Linux archive, Windows archive, and -`RELEASE-SHA256SUMS`, accepting the dual-platform CI/CD path end to end; `v0.1.0` remains unchanged. +2026-08-03. That historical release retains its then-current `OpenMaidEngine-Himegari-*` archive names; future +builds and releases use the `OME-*` names above. The resulting Gitea release exposes exactly the Linux archive, +Windows archive, and `RELEASE-SHA256SUMS`, accepting the dual-platform CI/CD path end to end; `v0.1.0` remains +unchanged. Code signing, an installer, Windows-on-Linux execution, and retroactively modifying the accepted Linux-only `v0.1.0` release are outside this effort. A future signing slice can use `osslsigncode` and protected credentials @@ -191,7 +193,7 @@ entry. The system-font-only policy remains supported until the bundled-font opti | ADV font discovery/raster fidelity | `Age.Engine.Text` remains OS-neutral. On compatible ACP-932 Windows, `auto` selects the separate exact-to-request `Age.Engine.Text.Windows` GDI gray-4 backend. Otherwise Godot TextServer supplies Unicode masks and metrics from ordered system-font substitutions in `godot/config/himegari-text-rendering.json`; this policy is explicitly not GDI pixel-exact. Immediate `0x204`/`0x205`, live ADV, retained History, and the wait atlas all enter ordinary RGBA surfaces/retained handles | Three Mincho/Gothic regular/bold samples byte-match an independent Unicode GDI oracle. A live `SC0000@0x869` trace proves that the `AGE Patch.exe`/`jprun.dll` wrapper overrides authored Mincho to MS Gothic: 13 captured masks match Gothic byte-for-byte and Mincho 0/13. This is wrapper behavior, not the true-native default, and reproducing it is outside the compatibility target. Forced exact and forced portable self-tests cover immediate, live, and History rasterization, bounded caching, complete-line materialization, retained ordering, alpha/tint/fade, transforms, clipping, capture, HIDEWIN suspension, partial erase/republication, reset, and teardown. Gameplay `Label` pools and overlay projection are gone | Select and smoke-test a redistributable Linux font-bundling policy or retain the explicit system-font prerequisite; add macOS runtime coverage and keep the GDI project out of non-Windows deliverables | | Filesystem semantics | Several filename and containment comparisons use `OrdinalIgnoreCase`; installed assets are conventionally uppercase | Needs validation on case-sensitive filesystems; may hide casing or containment mistakes | Add Linux/macOS tests with mixed-case synthetic roots and use filesystem-appropriate containment rules | | Save/profile/settings storage | `Sys4PersistencePaths` models AGE's independent `SAVEPATH` and `REGFILEPATH` resolutions. Godot replaces Himegari's related profile directory with `user://`, yielding `user://SAVE` for native S3SD/S4SD/S3RT files and thumbnails plus `user://SYS4REG.INI` for the BOM-less CP932 options file; the preserving writer changes only its nine `[sound]` keys | Save payloads and engine options are isolated together without changing either native format. Native/drop-in resolution remains available through `USEAPPDATAFOLDER` plus both SYS4INI paths. A single-root override is rejected when `SAVEPATH` is not beneath `REGFILEPATH`, preventing cross-profile guesses | Expose explicit profile/native selection through the future launcher and allow independent overrides for profiles whose two native paths are unrelated. Validate CP932 availability, replace/flush, case, permissions, and interrupted-write behavior on each export target | -| Game-install, runtime metadata, and repository discovery | `GameRootSelection` accepts `--game-root`, then probes the executable directory and current working directory for `SYS4INI.BIN`; on Unix the frontend prefers inherited shell `PWD` because Godot may change the process directory during project startup. Godot injects the selected root into its catalog and loose-first ALF store. `Himegari.csproj` embeds generated `build/opcodes.json`, and the frontend loads that assembly resource rather than `Paths.OpcodesJson`. Development/test `Paths.cs` finds the repository by tracked `global.json`, solution, and opcode-map markers rather than a checkout-directory name | Installed game data and packaged VM metadata no longer depend on the workspace sibling layout. The Linux export passed an explicit absolute game root outside the repository and read the installed archives; a source-only core proof also passes from an arbitrary repository directory name. Exported automatic page maps use `user://diagnostics/page-maps`; editor/development runs preserve `build/page-map-.jsonl` | Let the future profile launcher pass `--game-root`, and run executable-directory/CWD plus case/permission smoke gates on Linux and macOS | +| Game-install, runtime metadata, and repository discovery | `GameRootSelection` accepts `--game-root`, then probes the executable directory and current working directory for `SYS4INI.BIN`; on Unix the frontend prefers inherited shell `PWD` because Godot may change the process directory during project startup. Godot injects the selected root into its catalog and loose-first ALF store. `OME.csproj` embeds generated `build/opcodes.json`, and the frontend loads that assembly resource rather than `Paths.OpcodesJson`. Development/test `Paths.cs` finds the repository by tracked `global.json`, solution, and opcode-map markers rather than a checkout-directory name | Installed game data and packaged VM metadata no longer depend on the workspace sibling layout. The Linux export passed an explicit absolute game root outside the repository and read the installed archives; a source-only core proof also passes from an arbitrary repository directory name. Exported automatic page maps use `user://diagnostics/page-maps`; editor/development runs preserve `build/page-map-.jsonl` | Let the future profile launcher pass `--game-root`, and run executable-directory/CWD plus case/permission smoke gates on Linux and macOS | | Archive parity oracle | One integration test can launch a machine-local `bin/BinExtractALF.exe`; the binary and matching DLL are ignored and have unverified redistribution terms | Windows-only installed-data helper, not a shipped runtime dependency | Keep it in an explicit private workspace gate; runtime ALF/AAI readers do not depend on it | | Native RE tools | Frida/Ghidra helpers target the original `AGE.EXE`; PE-sieve was tried and replaced by the Frida import-map workflow | Development/research only; no native RE executable is tracked | Keep separate from export requirements; document platform prerequisites per tool | | Python workflow and core CI | The operating guide uses Windows `py -3.11`; `validate.py` launches child tools through `sys.executable` and has POSIX process-group cleanup plus `ps`-based leak auditing | The 590 engine cases are explicitly split into 502 source-only core cases and 88 `Workspace` installed-data/native-oracle cases; both selections pass with zero skips. The opcode-bootstrap unit injects synthetic observations while production bootstrap retains real-corpus scanning. `.gitea/workflows/core-validation.yml` uses the target server's demonstrated `ubuntu-latest`, checkout/setup-dotnet v4, setup-python v6, and Gitea artifact action baseline. A standalone arbitrary-name, corpus-free repository passes the complete core driver. The sanitized history is published on the private remote's default `develop` branch; the first hosted Linux core run succeeded on 2026-08-03 before sanitation at the tree now represented by `524ea74`, and the hosted gate succeeded again on the sanitized lineage at `d673652` | Retain Windows-native GDI parity and private installed-game/runtime checks as separate trusted gates; keep the hosted core gate required for future integration policy | @@ -336,7 +338,7 @@ PE/bundle verifier. The managed resolver accepts 280x352/866 ms, `MVB908` 400x400/333 ms, and `CHAPTER` 800x600/12016 ms, all with changing frames and nondecreasing timestamps. Malformed input and repeated teardown are covered. This is not yet distributable packaging. `FfmpegMovieDecoder` now adds cancellable timestamp pacing and is the live selection. The Godot build -copies the shim, five required shared libraries, and FFmpeg license beside `Himegari.dll`; a natural SYSTEM4 +copies the shim, five required shared libraries, and FFmpeg license beside `OME.dll`; a natural SYSTEM4 smoke completed 7288 ms `LOGO.AGF`, opened 106919 ms `OP.AGF`, and published frames from both without loading DirectShow; the user subsequently confirmed both opening movies work in normal windowed playback. DirectShow was deleted after the later synchronized-audio gate. Full export/source-offer packaging, Linux Godot runtime @@ -348,11 +350,11 @@ five required SONAME libraries and license under disposable `build/native/linux- `RUNPATH=$ORIGIN`, every FFmpeg dependency resolves beside it, and the bundle's newest required glibc symbol is 2.28, matching the provider baseline enforced by the build script. A self-contained Linux corpus-gate executable under Ubuntu 20.04 decoded all 213 installed payloads with 0 failures in 10.696 seconds. A zero-warning -`ExportRelease` Linux-target assembly build staged the shim, five libraries, and license beside `Himegari.dll` +`ExportRelease` Linux-target assembly build staged the shim, five libraries, and license beside `OME.dll` without the Windows GDI assembly or DLLs. The Godot Linux-x64 artifact pipeline landed the same day. `godot/export_presets.cfg` and the .NET-export-required -`godot/Himegari.sln` are committed; `tools/export-linux-x64.ps1` replaces only its exact disposable output, +`godot/OME.sln` are committed; `tools/export-linux-x64.ps1` replaces only its exact disposable output, performs a bounded Godot shutdown, verifies the complete artifact, and rejects Windows-only runtime files. `godot/build/.gdignore` prevents historical capture frames from being imported and packed. The exported ELF64 x86-64 executable, PCK, self-contained .NET runtime, and local FFmpeg bundle passed `--selftest` under Ubuntu/WSL diff --git a/docs/tools-reference.md b/docs/tools-reference.md index ca56625..58ce70f 100644 --- a/docs/tools-reference.md +++ b/docs/tools-reference.md @@ -307,8 +307,8 @@ Windows target, a native C compiler/binutils for Linux, and the ordinary archive The managed isolated probes load from `AGE_FFMPEG_NATIVE_DIR` when set, then application-local and `runtimes//native` locations. Build the target shim before running the `FfmpegShim*` tests; no original-game -movie is copied into the repository or native output. A target-aware `dotnet build godot/Himegari.csproj` -stages the matching shim, five shared-library dependencies, and `FFmpeg-LICENSE.txt` beside `Himegari.dll` +movie is copied into the repository or native output. A target-aware `dotnet build godot/OME.csproj` +stages the matching shim, five shared-library dependencies, and `FFmpeg-LICENSE.txt` beside `OME.dll` when the corresponding `build/native/win-x64/` or `build/native/linux-x64/` bundle exists. The current native movie ABI is version 3. In addition to sequential video/audio decode, it exposes a @@ -382,7 +382,7 @@ at 2.5M lines). All observe-only → parity preserved; all on `run`/`play`/`swee `godot --path godot -- --scene SC0000 --boot --shot out/p1.png --trace-histogram out/hist.txt`. **Godot frontend** (Godot 4.7 .NET; project = `godot/`). Toolchain: `godot --headless --path godot ---import` → `dotnet build godot/Himegari.csproj` → `godot [--headless] --path godot [-- ]`. +--import` → `dotnet build godot/OME.csproj` → `godot [--headless] --path godot [-- ]`. Plays the real bytecode with call-script execution on (subroutines run live). The game root is selected before catalog loading: `--game-root ` wins, otherwise the directory containing the running executable is tried, then the current working directory. A candidate must contain `SYS4INI.BIN`; invalid @@ -391,7 +391,7 @@ resolved against the current working directory, and repeated overrides use the l Godot preserves the shell launch directory through inherited `PWD` because editor/project startup may change the process directory before managed code runs. -**Linux x64 export** uses the committed `godot/export_presets.cfg` preset and `godot/Himegari.sln`: +**Linux x64 export** uses the committed `godot/export_presets.cfg` preset and `godot/OME.sln`: For the complete Linux-native release path, run from `age-reimpl/`: @@ -419,10 +419,10 @@ The packager adds `LICENSE`, `README.md`, `THIRD_PARTY_NOTICES.md`, a source/dep `BUILD-INFO.json`, and per-file `SHA256SUMS` to a stable top-level directory. It normalizes archive ownership, modes, ordering, and timestamps using `SOURCE_DATE_EPOCH` or the source commit time. Outputs are the loose export under `build/export/linux-x64/`, the staged installation and `package-smoke.log` under -`build/package/`, and `build/package/OpenMaidEngine-Himegari-linux-x64.tar.gz`. +`build/package/`, and `build/package/OME-linux-x64.tar.gz`. Before reporting success, the command launches the staged executable as -`Himegari.x86_64 --headless -- --package-smoke`. This asset-independent mode runs before game-root discovery +`OME --headless -- --package-smoke`. This asset-independent mode runs before game-root discovery and proves that the packaged managed assembly can read all 548 embedded opcode records and dynamically load the bundled native movie shim plus its local FFmpeg dependencies at ABI version 3. It does not exercise game archives, fonts, rendering, audio output, or a desktop window; retain the installed-game self-test below as a @@ -452,9 +452,10 @@ It regenerates runtime metadata, builds and statically verifies the pinned Windo exact self-contained `ExportRelease/win-x64` managed runtime, and performs the real Godot `Windows x86_64` release export. No produced Windows program is executed. `package_windows_x64.py` requires the Godot AMD64 EXE, PCK, self-contained runtime, project assemblies including `Age.Engine.Text.Windows.dll`, and FFmpeg DLL/license -set; it rejects Linux shared objects and embeds `BUILD-INFO.json`, `WINDOWS-VERIFICATION.json`, notices, and a +set; it rejects Linux shared objects and the legacy `Himegari.dll` name, and embeds `BUILD-INFO.json`, +`WINDOWS-VERIFICATION.json`, notices, and a complete `SHA256SUMS`. The normalized output is -`build/package/windows-x64/OpenMaidEngine-Himegari-windows-x64.zip`. +`build/package/windows-x64/OME-windows-x64.zip`. Focused commands are: @@ -469,7 +470,7 @@ The package verifier needs `x86_64-w64-mingw32-objdump` unless `--objdump` names Windows host, an extracted package can optionally run the same asset-independent dynamic gate as Linux: ```powershell -.\Himegari.exe --headless -- --package-smoke +.\OME.exe --headless -- --package-smoke ``` That command proves the embedded 548-opcode table and local FFmpeg ABI 3 load. It is a manual acceptance aid, @@ -486,8 +487,8 @@ Install the Godot 4.7 .NET export templates first and build the pinned native bu only `build/export/linux-x64`, invokes the release preset with a bounded headless shutdown, then calls the same Python payload verifier used by the Linux pipeline. The verifier checks the executable/PCK/self-contained managed payload plus all six project-owned FFmpeg files and rejects the Windows GDI adapter and Windows FFmpeg -DLLs. Output is `build/export/linux-x64/Himegari.x86_64` with its -PCK and `data_Himegari_linuxbsd_x86_64/` runtime directory. Do not relocate only the executable; the three +DLLs as well as the legacy `Himegari.dll` name. Output is `build/export/linux-x64/OME` with `OME.pck` and the +`data_OME_linuxbsd_x86_64/` runtime directory. Do not relocate only the executable; the three items are one artifact. The portable font policy requires a Japanese-capable system font. A minimal Ubuntu install needs, for @@ -495,7 +496,7 @@ example, `sudo apt install fonts-noto-cjk`; absence is a startup failure rather output. The exported headless smoke command is: ```bash -./build/export/linux-x64/Himegari.x86_64 --headless -- \ +./build/export/linux-x64/OME --headless -- \ --selftest --game-root "/absolute/path/to/Himegari_Game" --text-backend portable ``` diff --git a/engine/Age.Engine.Frontend/Properties/AssemblyInfo.cs b/engine/Age.Engine.Frontend/Properties/AssemblyInfo.cs index 626ea33..fad5b42 100644 --- a/engine/Age.Engine.Frontend/Properties/AssemblyInfo.cs +++ b/engine/Age.Engine.Frontend/Properties/AssemblyInfo.cs @@ -2,4 +2,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Age.Engine.Tests")] [assembly: InternalsVisibleTo("Age.MovieCorpusGate")] -[assembly: InternalsVisibleTo("Himegari")] +[assembly: InternalsVisibleTo("OME")] diff --git a/godot/Main.PackageSmoke.cs b/godot/Main.PackageSmoke.cs index 4aa45ed..f78f6fa 100644 --- a/godot/Main.PackageSmoke.cs +++ b/godot/Main.PackageSmoke.cs @@ -10,7 +10,7 @@ public partial class Main if (!OS.HasFeature("linux") && !OS.HasFeature("windows")) throw new PlatformNotSupportedException( "the packaged-runtime smoke gate supports Linux and Windows x64"); - var table = HimegariRuntimeMetadata.LoadOpcodeTable(); + var table = OmeRuntimeMetadata.LoadOpcodeTable(); if (table.Count != 548) throw new InvalidOperationException( $"embedded opcode table has {table.Count} entries; expected 548"); diff --git a/godot/Main.SelfTest.cs b/godot/Main.SelfTest.cs index 221a1c5..50b01cb 100644 --- a/godot/Main.SelfTest.cs +++ b/godot/Main.SelfTest.cs @@ -16,7 +16,7 @@ public partial class Main // and deferred main-thread calls) drives the VM identically to a headless run. private void RunSelfTest() { - var table = HimegariRuntimeMetadata.LoadOpcodeTable(); + var table = OmeRuntimeMetadata.LoadOpcodeTable(); var (script, provider) = BuildSelfTestScene(table); var headless = new VirtualMachine(script, table, new CaptureHost(), null, provider); headless.Run(); diff --git a/godot/Main.cs b/godot/Main.cs index 3219c6d..17fda68 100644 --- a/godot/Main.cs +++ b/godot/Main.cs @@ -240,7 +240,7 @@ public partial class Main : Godot.Control _clock.Speed = System.Math.Clamp(speed, 0.05, 8.0); GD.Print($"[renderer] retained backend={(_useGpuBackend ? "gpu" : "software")}"); - var table = HimegariRuntimeMetadata.LoadOpcodeTable(); + var table = OmeRuntimeMetadata.LoadOpcodeTable(); // Persistence retains AGE's native filenames and formats, but the port owns one profile-root // interception point. Himegari's SYS4INI makes SAVEPATH the SAVE child of REGFILEPATH, so both // save payloads and SYS4REG.INI remain isolated together under Godot's user directory. diff --git a/godot/Himegari.csproj b/godot/OME.csproj similarity index 97% rename from godot/Himegari.csproj rename to godot/OME.csproj index 19a5bf6..06a863e 100644 --- a/godot/Himegari.csproj +++ b/godot/OME.csproj @@ -15,7 +15,7 @@ + LogicalName="OME.Runtime.opcodes.json" /> diff --git a/godot/Himegari.sln b/godot/OME.sln similarity index 93% rename from godot/Himegari.sln rename to godot/OME.sln index afb98ed..ebe3a22 100644 --- a/godot/Himegari.sln +++ b/godot/OME.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Himegari", "Himegari.csproj", "{5821B505-EBD3-4B50-A83A-7AFE22AA1528}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OME", "OME.csproj", "{5821B505-EBD3-4B50-A83A-7AFE22AA1528}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Age.Engine.Frontend", "..\engine\Age.Engine.Frontend\Age.Engine.Frontend.csproj", "{2B018D3E-4057-465E-89CB-4CC77FDD60E2}" EndProject diff --git a/godot/HimegariRuntimeMetadata.cs b/godot/OmeRuntimeMetadata.cs similarity index 67% rename from godot/HimegariRuntimeMetadata.cs rename to godot/OmeRuntimeMetadata.cs index 1ba4a34..703b020 100644 --- a/godot/HimegariRuntimeMetadata.cs +++ b/godot/OmeRuntimeMetadata.cs @@ -5,16 +5,16 @@ using Age.Engine.Model; using Age.Engine.Sys4; /// -/// Himegari profile metadata that must travel with every Godot build. Repository discovery belongs to +/// OME profile metadata that must travel with every Godot build. Repository discovery belongs to /// development tooling; exported runtimes read the generator output embedded into this assembly. /// -internal static class HimegariRuntimeMetadata +internal static class OmeRuntimeMetadata { - internal const string OpcodeTableResourceName = "Himegari.Runtime.opcodes.json"; + internal const string OpcodeTableResourceName = "OME.Runtime.opcodes.json"; internal static OpcodeTable LoadOpcodeTable() { - Assembly assembly = typeof(HimegariRuntimeMetadata).Assembly; + Assembly assembly = typeof(OmeRuntimeMetadata).Assembly; using Stream stream = assembly.GetManifestResourceStream(OpcodeTableResourceName) ?? throw new InvalidDataException( $"Embedded runtime metadata '{OpcodeTableResourceName}' is missing from " + diff --git a/godot/export_presets.cfg b/godot/export_presets.cfg index 821e34a..ab81726 100644 --- a/godot/export_presets.cfg +++ b/godot/export_presets.cfg @@ -8,7 +8,7 @@ custom_features="" export_filter="all_resources" include_filter="" exclude_filter="" -export_path="../build/export/linux-x64/Himegari.x86_64" +export_path="../build/export/linux-x64/OME" patches=PackedStringArray() encryption_include_filters="" encryption_exclude_filters="" @@ -41,7 +41,7 @@ custom_features="" export_filter="all_resources" include_filter="" exclude_filter="" -export_path="../build/export/windows-x64/Himegari.exe" +export_path="../build/export/windows-x64/OME.exe" patches=PackedStringArray() encryption_include_filters="" encryption_exclude_filters="" diff --git a/godot/project.godot b/godot/project.godot index 9a94045..623ea78 100644 --- a/godot/project.godot +++ b/godot/project.godot @@ -9,7 +9,7 @@ window/size/viewport_width=640 window/size/viewport_height=480 [dotnet] -project/assembly_name="Himegari" +project/assembly_name="OME" [rendering] environment/defaults/default_clear_color=Color(0, 0, 0, 1) diff --git a/run-godot.ps1 b/run-godot.ps1 index 509f237..6abcc6d 100644 --- a/run-godot.ps1 +++ b/run-godot.ps1 @@ -28,7 +28,7 @@ param( $ErrorActionPreference = 'Stop' $repo = $PSScriptRoot # age-reimpl/ $project = Join-Path $repo 'godot' -$csproj = Join-Path $project 'Himegari.csproj' +$csproj = Join-Path $project 'OME.csproj' function Resolve-ConfiguredFile { param( diff --git a/tools/build-linux-x64.sh b/tools/build-linux-x64.sh index aa839ee..8584f17 100755 --- a/tools/build-linux-x64.sh +++ b/tools/build-linux-x64.sh @@ -39,7 +39,7 @@ DOTNET_CLI_USE_MSBUILD_SERVER=0 \ MSBUILDDISABLENODEREUSE=1 \ DOTNET_gcServer=0 \ DOTNET_GCConserveMemory=9 \ -dotnet publish "$project_root/Himegari.csproj" \ +dotnet publish "$project_root/OME.csproj" \ --configuration ExportRelease \ --runtime linux-x64 \ --self-contained true \ @@ -61,7 +61,7 @@ if [[ "$managed_proxy_directory" != "$expected_managed_proxy_directory" || "$man fi rm -rf -- "$managed_proxy_directory" mkdir -p -- "$managed_proxy_directory" -cp -- "$managed_publish_directory/Himegari.dll" "$managed_proxy_directory/Himegari.dll" +cp -- "$managed_publish_directory/OME.dll" "$managed_proxy_directory/OME.dll" real_dotnet="$(command -v dotnet)" expected_dotnet_proxy_directory="$repo_root/build/dotnet-export-proxy" @@ -90,15 +90,15 @@ RestoreDisableParallel=true \ DOTNET_gcServer=0 \ DOTNET_GCConserveMemory=9 \ AGE_REAL_DOTNET="$real_dotnet" \ -AGE_PUBLISH_PROJECT="$project_root/Himegari.csproj" \ +AGE_PUBLISH_PROJECT="$project_root/OME.csproj" \ AGE_PREPUBLISHED_OUTPUT="$managed_proxy_directory" \ AGE_PUBLISH_OUTPUT_ROOT="${TMPDIR:-/tmp}/godot-publish-dotnet" \ -AGE_PUBLISH_ASSEMBLY="Himegari.dll" \ +AGE_PUBLISH_ASSEMBLY="OME.dll" \ AGE_PUBLISH_RUNTIME="linux-x64" \ PATH="$dotnet_proxy_directory:$PATH" \ XDG_DATA_HOME="$xdg_data_home" "$godot_console" \ --headless --quit-after 120 --path "$project_root" \ - --export-release "Linux x86_64" "$export_directory/Himegari.x86_64" + --export-release "Linux x86_64" "$export_directory/OME" export_status=$? set -e if [[ $export_status -ne 0 ]]; then @@ -108,8 +108,8 @@ if [[ $export_status -ne 0 ]]; then exit "$export_status" fi -managed_export_directory="$export_directory/data_Himegari_linuxbsd_x86_64" -expected_managed_export_directory="$repo_root/build/export/linux-x64/data_Himegari_linuxbsd_x86_64" +managed_export_directory="$export_directory/data_OME_linuxbsd_x86_64" +expected_managed_export_directory="$repo_root/build/export/linux-x64/data_OME_linuxbsd_x86_64" if [[ "$managed_export_directory" != "$expected_managed_export_directory" || "$managed_export_directory" == "/" ]]; then echo "refusing to replace unexpected managed export directory: $managed_export_directory" >&2 exit 1 @@ -131,7 +131,7 @@ package_root="${package_outputs[0]}" archive_path="${package_outputs[1]}" smoke_log="$package_directory/package-smoke.log" set +e -"$package_root/Himegari.x86_64" --headless -- --package-smoke >"$smoke_log" 2>&1 +"$package_root/OME" --headless -- --package-smoke >"$smoke_log" 2>&1 smoke_status=$? set -e cat "$smoke_log" diff --git a/tools/build-windows-x64.sh b/tools/build-windows-x64.sh index 1fa85cb..87a83da 100755 --- a/tools/build-windows-x64.sh +++ b/tools/build-windows-x64.sh @@ -39,7 +39,7 @@ DOTNET_CLI_USE_MSBUILD_SERVER=0 \ MSBUILDDISABLENODEREUSE=1 \ DOTNET_gcServer=0 \ DOTNET_GCConserveMemory=9 \ -dotnet publish "$project_root/Himegari.csproj" \ +dotnet publish "$project_root/OME.csproj" \ --configuration ExportRelease \ --runtime win-x64 \ --self-contained true \ @@ -58,7 +58,7 @@ if [[ "$managed_proxy_directory" != "$expected_managed_proxy_directory" || "$man fi rm -rf -- "$managed_proxy_directory" mkdir -p -- "$managed_proxy_directory" -cp -- "$managed_publish_directory/Himegari.dll" "$managed_proxy_directory/Himegari.dll" +cp -- "$managed_publish_directory/OME.dll" "$managed_proxy_directory/OME.dll" real_dotnet="$(command -v dotnet)" expected_dotnet_proxy_directory="$repo_root/build/dotnet-export-proxy" @@ -87,15 +87,15 @@ RestoreDisableParallel=true \ DOTNET_gcServer=0 \ DOTNET_GCConserveMemory=9 \ AGE_REAL_DOTNET="$real_dotnet" \ -AGE_PUBLISH_PROJECT="$project_root/Himegari.csproj" \ +AGE_PUBLISH_PROJECT="$project_root/OME.csproj" \ AGE_PREPUBLISHED_OUTPUT="$managed_proxy_directory" \ AGE_PUBLISH_OUTPUT_ROOT="${TMPDIR:-/tmp}/godot-publish-dotnet" \ -AGE_PUBLISH_ASSEMBLY="Himegari.dll" \ +AGE_PUBLISH_ASSEMBLY="OME.dll" \ AGE_PUBLISH_RUNTIME="win-x64" \ PATH="$dotnet_proxy_directory:$PATH" \ XDG_DATA_HOME="$xdg_data_home" "$godot_console" \ --headless --quit-after 120 --path "$project_root" \ - --export-release "Windows x86_64" "$export_directory/Himegari.exe" + --export-release "Windows x86_64" "$export_directory/OME.exe" export_status=$? set -e if [[ $export_status -ne 0 ]]; then @@ -105,8 +105,8 @@ if [[ $export_status -ne 0 ]]; then exit "$export_status" fi -managed_export_directory="$export_directory/data_Himegari_windows_x86_64" -expected_managed_export_directory="$repo_root/build/export/windows-x64/data_Himegari_windows_x86_64" +managed_export_directory="$export_directory/data_OME_windows_x86_64" +expected_managed_export_directory="$repo_root/build/export/windows-x64/data_OME_windows_x86_64" if [[ "$managed_export_directory" != "$expected_managed_export_directory" || "$managed_export_directory" == "/" ]]; then echo "refusing to replace unexpected managed export directory: $managed_export_directory" >&2 exit 1 diff --git a/tools/export-linux-x64.ps1 b/tools/export-linux-x64.ps1 index 7aad0e4..9cf9d38 100644 --- a/tools/export-linux-x64.ps1 +++ b/tools/export-linux-x64.ps1 @@ -9,13 +9,13 @@ $projectRoot = Join-Path $repoRoot 'godot' $godotConsolePath = (Resolve-Path -LiteralPath $GodotConsole).Path $outputDirectory = [System.IO.Path]::GetFullPath((Join-Path $repoRoot 'build\export\linux-x64')) $expectedOutputDirectory = [System.IO.Path]::GetFullPath((Join-Path $repoRoot 'build\export\linux-x64')) -$executable = Join-Path $outputDirectory 'Himegari.x86_64' +$executable = Join-Path $outputDirectory 'OME' if (-not (Test-Path -LiteralPath $godotConsolePath -PathType Leaf)) { throw "Godot console executable was not found: $godotConsolePath" } foreach ($required in @( - (Join-Path $projectRoot 'Himegari.sln'), + (Join-Path $projectRoot 'OME.sln'), (Join-Path $projectRoot 'export_presets.cfg'), (Join-Path $repoRoot 'build\native\linux-x64\libage_movie_ffmpeg.so') )) { diff --git a/tools/package_linux_x64.py b/tools/package_linux_x64.py index c817437..3ef5591 100755 --- a/tools/package_linux_x64.py +++ b/tools/package_linux_x64.py @@ -15,12 +15,12 @@ from pathlib import Path HERE = Path(__file__).resolve().parent REPO = HERE.parent -MANAGED_DIRECTORY = "data_Himegari_linuxbsd_x86_64" -PACKAGE_NAME = "OpenMaidEngine-Himegari-linux-x64" +MANAGED_DIRECTORY = "data_OME_linuxbsd_x86_64" +PACKAGE_NAME = "OME-linux-x64" REQUIRED_FILES = ( - "Himegari.x86_64", - "Himegari.pck", - f"{MANAGED_DIRECTORY}/Himegari.dll", + "OME", + "OME.pck", + f"{MANAGED_DIRECTORY}/OME.dll", f"{MANAGED_DIRECTORY}/Age.Engine.dll", f"{MANAGED_DIRECTORY}/Age.Engine.Frontend.dll", f"{MANAGED_DIRECTORY}/libage_movie_ffmpeg.so", @@ -36,6 +36,7 @@ FORBIDDEN_FILES = ( f"{MANAGED_DIRECTORY}/age_movie_ffmpeg.dll", f"{MANAGED_DIRECTORY}/avformat-62.dll", ) +LEGACY_FILES = (f"{MANAGED_DIRECTORY}/Himegari.dll",) PROJECT_FILES = ("LICENSE", "README.md", "THIRD_PARTY_NOTICES.md") @@ -54,7 +55,10 @@ def verify_export(export_directory: Path) -> Path: forbidden = [name for name in FORBIDDEN_FILES if (export_directory / name).exists()] if forbidden: raise ValueError("Linux export contains Windows-only files: " + ", ".join(forbidden)) - executable = export_directory / "Himegari.x86_64" + legacy = [name for name in LEGACY_FILES if (export_directory / name).exists()] + if legacy: + raise ValueError("Linux export contains legacy-branded files: " + ", ".join(legacy)) + executable = export_directory / "OME" if os.name != "nt" and not os.access(executable, os.X_OK): raise ValueError(f"Linux export executable bit is not set: {executable}") return export_directory @@ -89,7 +93,7 @@ def build_metadata(epoch: int) -> dict[str, object]: dirty = bool(_git("status", "--porcelain", "--untracked-files=normal")) return { "schema_version": 1, - "project": "OpenMaidEngine Himegari profile", + "project": "Open Maid Engine", "target": "linux-x64", "source_commit": _git("rev-parse", "HEAD"), "source_dirty": dirty, diff --git a/tools/package_windows_x64.py b/tools/package_windows_x64.py index 5b5bde6..307f97a 100755 --- a/tools/package_windows_x64.py +++ b/tools/package_windows_x64.py @@ -18,12 +18,12 @@ import verify_windows_native HERE = Path(__file__).resolve().parent REPO = HERE.parent -MANAGED_DIRECTORY = "data_Himegari_windows_x86_64" -PACKAGE_NAME = "OpenMaidEngine-Himegari-windows-x64" +MANAGED_DIRECTORY = "data_OME_windows_x86_64" +PACKAGE_NAME = "OME-windows-x64" REQUIRED_FILES = ( - "Himegari.exe", - "Himegari.pck", - f"{MANAGED_DIRECTORY}/Himegari.dll", + "OME.exe", + "OME.pck", + f"{MANAGED_DIRECTORY}/OME.dll", f"{MANAGED_DIRECTORY}/Age.Engine.dll", f"{MANAGED_DIRECTORY}/Age.Engine.Frontend.dll", f"{MANAGED_DIRECTORY}/Age.Engine.Text.Windows.dll", @@ -34,10 +34,11 @@ REQUIRED_FILES = ( *(f"{MANAGED_DIRECTORY}/{name}" for name in verify_windows_native.REQUIRED_FILES), ) FORBIDDEN_FILES = ( - "Himegari.x86_64", + "OME", f"{MANAGED_DIRECTORY}/libage_movie_ffmpeg.so", f"{MANAGED_DIRECTORY}/libavformat.so.62", ) +LEGACY_FILES = (f"{MANAGED_DIRECTORY}/Himegari.dll",) PROJECT_FILES = ("LICENSE", "README.md", "THIRD_PARTY_NOTICES.md") @@ -61,10 +62,13 @@ def verify_export(export_directory: Path, objdump: str) -> tuple[Path, dict[str, ) if forbidden: raise ValueError("Windows export contains Linux-only files: " + ", ".join(sorted(set(forbidden)))) - executable_machine = verify_windows_native.pe_machine(export_directory / "Himegari.exe") + legacy = [name for name in LEGACY_FILES if (export_directory / name).exists()] + if legacy: + raise ValueError("Windows export contains legacy-branded files: " + ", ".join(legacy)) + executable_machine = verify_windows_native.pe_machine(export_directory / "OME.exe") if executable_machine != verify_windows_native.PE_MACHINE_AMD64: raise ValueError( - f"Windows executable is not AMD64 PE (0x{executable_machine:04x}): Himegari.exe" + f"Windows executable is not AMD64 PE (0x{executable_machine:04x}): OME.exe" ) native_report = verify_windows_native.verify_bundle( export_directory / MANAGED_DIRECTORY, @@ -113,7 +117,7 @@ def build_metadata(epoch: int) -> dict[str, object]: ffmpeg = json.load(stream) return { "schema_version": 1, - "project": "OpenMaidEngine Himegari profile", + "project": "Open Maid Engine", "target": "win-x64", "source_commit": _git("rev-parse", "HEAD"), "source_dirty": bool(_git("status", "--porcelain", "--untracked-files=normal")), diff --git a/tools/publish_gitea_release.py b/tools/publish_gitea_release.py index be73911..ee43d7a 100755 --- a/tools/publish_gitea_release.py +++ b/tools/publish_gitea_release.py @@ -20,8 +20,8 @@ from typing import Any, Callable, Protocol import verify_windows_native -LINUX_ARCHIVE = "OpenMaidEngine-Himegari-linux-x64.tar.gz" -WINDOWS_ARCHIVE = "OpenMaidEngine-Himegari-windows-x64.zip" +LINUX_ARCHIVE = "OME-linux-x64.tar.gz" +WINDOWS_ARCHIVE = "OME-windows-x64.zip" RELEASE_CHECKSUMS = "RELEASE-SHA256SUMS" LINUX_ARTIFACT_FILES = frozenset({ LINUX_ARCHIVE, @@ -38,8 +38,8 @@ WINDOWS_ARTIFACT_FILES = frozenset({ "WINDOWS-VERIFICATION.json", }) EXPECTED_RELEASE_ASSETS = frozenset({LINUX_ARCHIVE, WINDOWS_ARCHIVE, RELEASE_CHECKSUMS}) -LINUX_PACKAGE_ROOT = "OpenMaidEngine-Himegari-linux-x64" -WINDOWS_PACKAGE_ROOT = "OpenMaidEngine-Himegari-windows-x64" +LINUX_PACKAGE_ROOT = "OME-linux-x64" +WINDOWS_PACKAGE_ROOT = "OME-windows-x64" SMOKE_MARKER = "PACKAGE SMOKE OK: opcodes=548 ffmpeg-abi=3" TAG_PATTERN = re.compile(r"v[0-9][0-9A-Za-z.+-]*\Z") COMMIT_PATTERN = re.compile(r"[0-9a-f]{40}\Z") @@ -279,8 +279,8 @@ def _validate_windows_verification(data: bytes) -> None: } if native.get("schema_version") != 1 or native.get("target") != "win-x64": mismatches["native"] = ((native.get("schema_version"), native.get("target")), (1, "win-x64")) - if native.get("bundle") != "data_Himegari_windows_x86_64": - mismatches["bundle"] = (native.get("bundle"), "data_Himegari_windows_x86_64") + if native.get("bundle") != "data_OME_windows_x86_64": + mismatches["bundle"] = (native.get("bundle"), "data_OME_windows_x86_64") if machines != expected_machines: mismatches["machines"] = (machines, expected_machines) exports_value = native.get("shim_exports") @@ -361,9 +361,9 @@ def prepare_release_assets( if external != internal: raise ValueError(f"external and packaged {label} do not match") - if b" Himegari.x86_64\n" not in linux_ledger: + if b" OME\n" not in linux_ledger: raise ValueError("Linux SHA256SUMS does not contain the packaged executable") - if b" Himegari.exe\n" not in windows_ledger: + if b" OME.exe\n" not in windows_ledger: raise ValueError("Windows SHA256SUMS does not contain the packaged executable") output_directory = output_directory.resolve() @@ -410,7 +410,7 @@ def promote_release( ) if {asset.name for asset in assets} != EXPECTED_RELEASE_ASSETS: raise RuntimeError("prepared release asset set is invalid") - title = f"OpenMaidEngine Himegari {tag}" + title = f"Open Maid Engine {tag}" release = api.get_release(tag) if release is None: release = api.create_release({ diff --git a/tools/test_dotnet_publish_proxy.py b/tools/test_dotnet_publish_proxy.py index 8cca306..9861081 100755 --- a/tools/test_dotnet_publish_proxy.py +++ b/tools/test_dotnet_publish_proxy.py @@ -12,11 +12,11 @@ class DotnetPublishProxyTests(unittest.TestCase): def test_stages_exact_expected_publish(self) -> None: with tempfile.TemporaryDirectory() as temporary: root = Path(temporary) - project = root / "Himegari.csproj" + project = root / "OME.csproj" project.write_text("", encoding="utf-8") source = root / "prepublished" source.mkdir() - (source / "Himegari.dll").write_bytes(b"managed") + (source / "OME.dll").write_bytes(b"managed") (source / "libhostfxr.so").write_bytes(b"runtime") output_root = root / "godot-publish-dotnet" output = output_root / "123-ExportRelease-linux-x64" @@ -29,26 +29,26 @@ class DotnetPublishProxyTests(unittest.TestCase): "AGE_PUBLISH_PROJECT": str(project), "AGE_PREPUBLISHED_OUTPUT": str(source), "AGE_PUBLISH_OUTPUT_ROOT": str(output_root), - "AGE_PUBLISH_ASSEMBLY": "Himegari.dll", + "AGE_PUBLISH_ASSEMBLY": "OME.dll", "AGE_PUBLISH_RUNTIME": "linux-x64", }) self.assertEqual(output.resolve(), staged) - self.assertEqual(b"managed", (staged / "Himegari.dll").read_bytes()) + self.assertEqual(b"managed", (staged / "OME.dll").read_bytes()) self.assertEqual(b"runtime", (staged / "libhostfxr.so").read_bytes()) def test_rejects_drift_and_output_escape(self) -> None: with tempfile.TemporaryDirectory() as temporary: root = Path(temporary) - project = root / "Himegari.csproj" + project = root / "OME.csproj" project.write_text("", encoding="utf-8") source = root / "prepublished" source.mkdir() - (source / "Himegari.dll").write_bytes(b"managed") + (source / "OME.dll").write_bytes(b"managed") environment = { "AGE_PUBLISH_PROJECT": str(project), "AGE_PREPUBLISHED_OUTPUT": str(source), "AGE_PUBLISH_OUTPUT_ROOT": str(root / "reserved"), - "AGE_PUBLISH_ASSEMBLY": "Himegari.dll", + "AGE_PUBLISH_ASSEMBLY": "OME.dll", "AGE_PUBLISH_RUNTIME": "linux-x64", } wrong_runtime = dotnet_publish_proxy.PublishRequest( @@ -65,11 +65,11 @@ class DotnetPublishProxyTests(unittest.TestCase): def test_stages_windows_publish_when_explicitly_selected(self) -> None: with tempfile.TemporaryDirectory() as temporary: root = Path(temporary) - project = root / "Himegari.csproj" + project = root / "OME.csproj" project.write_text("", encoding="utf-8") source = root / "prepublished" source.mkdir() - (source / "Himegari.dll").write_bytes(b"managed") + (source / "OME.dll").write_bytes(b"managed") output = root / "reserved/123-ExportRelease-win-x64" request = dotnet_publish_proxy.PublishRequest( project, "ExportRelease", "win-x64", "true", output @@ -78,7 +78,7 @@ class DotnetPublishProxyTests(unittest.TestCase): "AGE_PUBLISH_PROJECT": str(project), "AGE_PREPUBLISHED_OUTPUT": str(source), "AGE_PUBLISH_OUTPUT_ROOT": str(root / "reserved"), - "AGE_PUBLISH_ASSEMBLY": "Himegari.dll", + "AGE_PUBLISH_ASSEMBLY": "OME.dll", "AGE_PUBLISH_RUNTIME": "win-x64", }) self.assertEqual(output.resolve(), staged) diff --git a/tools/test_package_linux_x64.py b/tools/test_package_linux_x64.py index aaa6b96..3637d43 100755 --- a/tools/test_package_linux_x64.py +++ b/tools/test_package_linux_x64.py @@ -16,11 +16,24 @@ def make_export(root: Path) -> Path: path = export / relative path.parent.mkdir(parents=True, exist_ok=True) path.write_bytes(f"fixture:{relative}".encode()) - (export / "Himegari.x86_64").chmod(0o755) + (export / "OME").chmod(0o755) return export class PackageLinuxX64Tests(unittest.TestCase): + def test_public_output_names_use_ome_branding(self) -> None: + self.assertEqual("OME-linux-x64", package_linux_x64.PACKAGE_NAME) + self.assertIn("OME", package_linux_x64.REQUIRED_FILES) + self.assertIn("OME.pck", package_linux_x64.REQUIRED_FILES) + self.assertIn( + f"{package_linux_x64.MANAGED_DIRECTORY}/OME.dll", + package_linux_x64.REQUIRED_FILES, + ) + self.assertIn( + f"{package_linux_x64.MANAGED_DIRECTORY}/Himegari.dll", + package_linux_x64.LEGACY_FILES, + ) + def test_verify_rejects_missing_and_windows_files(self) -> None: with tempfile.TemporaryDirectory() as temporary: export = make_export(Path(temporary)) @@ -33,12 +46,17 @@ class PackageLinuxX64Tests(unittest.TestCase): forbidden.write_bytes(b"windows") with self.assertRaisesRegex(ValueError, "Windows-only"): package_linux_x64.verify_export(export) + forbidden.unlink() + legacy = export / package_linux_x64.LEGACY_FILES[0] + legacy.write_bytes(b"legacy") + with self.assertRaisesRegex(ValueError, "legacy-branded"): + package_linux_x64.verify_export(export) @unittest.skipIf(package_linux_x64.os.name == "nt", "executable-bit gate is POSIX-only") def test_verify_requires_executable_bit_on_posix(self) -> None: with tempfile.TemporaryDirectory() as temporary: export = make_export(Path(temporary)) - (export / "Himegari.x86_64").chmod(0o644) + (export / "OME").chmod(0o644) with self.assertRaisesRegex(ValueError, "executable bit"): package_linux_x64.verify_export(export) @@ -65,7 +83,7 @@ class PackageLinuxX64Tests(unittest.TestCase): self.assertTrue((package_root / "LICENSE").is_file()) self.assertTrue((package_root / "BUILD-INFO.json").is_file()) checksums = (package_root / "SHA256SUMS").read_text(encoding="utf-8") - self.assertIn("Himegari.x86_64", checksums) + self.assertIn("OME", checksums) self.assertIn("THIRD_PARTY_NOTICES.md", checksums) diff --git a/tools/test_package_windows_x64.py b/tools/test_package_windows_x64.py index fb64ded..918c553 100755 --- a/tools/test_package_windows_x64.py +++ b/tools/test_package_windows_x64.py @@ -33,7 +33,7 @@ def make_export(root: Path) -> Path: path = export / relative path.parent.mkdir(parents=True, exist_ok=True) path.write_bytes(f"fixture:{relative}".encode()) - write_pe(export / "Himegari.exe") + write_pe(export / "OME.exe") managed = export / package_windows_x64.MANAGED_DIRECTORY for name in (verify_windows_native.SHIM, *verify_windows_native.RUNTIME_DLLS): write_pe(managed / name) @@ -41,6 +41,19 @@ def make_export(root: Path) -> Path: class PackageWindowsX64Tests(unittest.TestCase): + def test_public_output_names_use_ome_branding(self) -> None: + self.assertEqual("OME-windows-x64", package_windows_x64.PACKAGE_NAME) + self.assertIn("OME.exe", package_windows_x64.REQUIRED_FILES) + self.assertIn("OME.pck", package_windows_x64.REQUIRED_FILES) + self.assertIn( + f"{package_windows_x64.MANAGED_DIRECTORY}/OME.dll", + package_windows_x64.REQUIRED_FILES, + ) + self.assertIn( + f"{package_windows_x64.MANAGED_DIRECTORY}/Himegari.dll", + package_windows_x64.LEGACY_FILES, + ) + def test_verify_rejects_missing_linux_and_wrong_machine_files(self) -> None: with tempfile.TemporaryDirectory() as temporary: export = make_export(Path(temporary)) @@ -56,7 +69,12 @@ class PackageWindowsX64Tests(unittest.TestCase): with self.assertRaisesRegex(ValueError, "Linux-only"): package_windows_x64.verify_export(export, "objdump") linux.unlink() - write_pe(export / "Himegari.exe", machine=0x014C) + legacy = export / package_windows_x64.LEGACY_FILES[0] + legacy.write_bytes(b"legacy") + with self.assertRaisesRegex(ValueError, "legacy-branded"): + package_windows_x64.verify_export(export, "objdump") + legacy.unlink() + write_pe(export / "OME.exe", machine=0x014C) with self.assertRaisesRegex(ValueError, "not AMD64"): package_windows_x64.verify_export(export, "objdump") @@ -88,7 +106,7 @@ class PackageWindowsX64Tests(unittest.TestCase): self.assertTrue((package_root / "BUILD-INFO.json").is_file()) self.assertTrue((package_root / "WINDOWS-VERIFICATION.json").is_file()) checksums = (package_root / "SHA256SUMS").read_text(encoding="utf-8") - self.assertIn("Himegari.exe", checksums) + self.assertIn("OME.exe", checksums) self.assertIn("THIRD_PARTY_NOTICES.md", checksums) diff --git a/tools/test_publish_gitea_release.py b/tools/test_publish_gitea_release.py index 3c04508..7f8bd17 100755 --- a/tools/test_publish_gitea_release.py +++ b/tools/test_publish_gitea_release.py @@ -49,7 +49,7 @@ def matching_release() -> dict[str, Any]: "id": 17, "tag_name": TAG, "target_commitish": TARGET, - "name": f"OpenMaidEngine Himegari {TAG}", + "name": f"Open Maid Engine {TAG}", "draft": False, "prerelease": False, "html_url": "https://gitea.invalid/releases/tag/v0.2.0", @@ -77,7 +77,7 @@ def windows_verification() -> bytes: "native": { "schema_version": 1, "target": "win-x64", - "bundle": "data_Himegari_windows_x86_64", + "bundle": "data_OME_windows_x86_64", "machines": { name: "AMD64" for name in (verify_windows_native.SHIM, *verify_windows_native.RUNTIME_DLLS) @@ -109,7 +109,7 @@ def create_artifacts(root: Path) -> tuple[Path, Path, Path]: windows.mkdir() linux_info = build_info("linux-x64") - linux_ledger = f"{'0' * 64} Himegari.x86_64\n".encode() + linux_ledger = f"{'0' * 64} OME\n".encode() linux_archive = linux / publish_gitea_release.LINUX_ARCHIVE with tarfile.open(linux_archive, "w:gz") as archive: add_tar_bytes( @@ -130,7 +130,7 @@ def create_artifacts(root: Path) -> tuple[Path, Path, Path]: write_checksum(linux, linux_archive) windows_info = build_info("win-x64") - windows_ledger = f"{'1' * 64} Himegari.exe\n".encode() + windows_ledger = f"{'1' * 64} OME.exe\n".encode() verification = windows_verification() windows_archive = windows / publish_gitea_release.WINDOWS_ARCHIVE with zipfile.ZipFile(windows_archive, "w", compression=zipfile.ZIP_DEFLATED) as archive: @@ -156,6 +156,7 @@ class PublishGiteaReleaseTests(unittest.TestCase): self.assertEqual(17, result["id"]) self.assertEqual(TAG, api.created_payload["tag_name"]) self.assertEqual(TARGET, api.created_payload["target_commitish"]) + self.assertEqual(f"Open Maid Engine {TAG}", api.created_payload["name"]) self.assertIn("Windows archive", api.created_payload["body"]) self.assertEqual( publish_gitea_release.EXPECTED_RELEASE_ASSETS, diff --git a/tools/test_release_workflow.py b/tools/test_release_workflow.py index 5984187..aadd686 100755 --- a/tools/test_release_workflow.py +++ b/tools/test_release_workflow.py @@ -8,6 +8,13 @@ from pathlib import Path REPO = Path(__file__).resolve().parent.parent WORKFLOW = REPO / ".gitea/workflows/linux-release-build.yml" +EXPORT_PRESETS = REPO / "godot/export_presets.cfg" +GODOT_PROJECT = REPO / "godot/project.godot" +MANAGED_PROJECT = REPO / "godot/OME.csproj" +MANAGED_SOLUTION = REPO / "godot/OME.sln" +LINUX_BUILD = REPO / "tools/build-linux-x64.sh" +WINDOWS_BUILD = REPO / "tools/build-windows-x64.sh" +WINDOWS_HOSTED_EXPORT = REPO / "tools/export-linux-x64.ps1" def job(text: str, name: str, next_name: str | None) -> str: @@ -23,6 +30,42 @@ class ReleaseWorkflowTests(unittest.TestCase): cls.linux = job(cls.text, "linux-release", "windows-release") cls.windows = job(cls.text, "windows-release", "publish-release") cls.publish = job(cls.text, "publish-release", None) + cls.export_presets = EXPORT_PRESETS.read_text(encoding="utf-8") + cls.godot_project = GODOT_PROJECT.read_text(encoding="utf-8") + cls.managed_project = MANAGED_PROJECT.read_text(encoding="utf-8") + cls.managed_solution = MANAGED_SOLUTION.read_text(encoding="utf-8") + cls.linux_build = LINUX_BUILD.read_text(encoding="utf-8") + cls.windows_build = WINDOWS_BUILD.read_text(encoding="utf-8") + cls.windows_hosted_export = WINDOWS_HOSTED_EXPORT.read_text(encoding="utf-8") + + def test_public_build_outputs_use_ome_branding(self) -> None: + self.assertIn('export_path="../build/export/linux-x64/OME"', self.export_presets) + self.assertIn('export_path="../build/export/windows-x64/OME.exe"', self.export_presets) + self.assertIn('project/assembly_name="OME"', self.godot_project) + self.assertIn('LogicalName="OME.Runtime.opcodes.json"', self.managed_project) + self.assertIn('= "OME", "OME.csproj"', self.managed_solution) + self.assertIn("'OME.sln'", self.windows_hosted_export) + self.assertFalse((REPO / "godot/Himegari.csproj").exists()) + self.assertFalse((REPO / "godot/Himegari.sln").exists()) + active_surfaces = "\n".join( + ( + self.text, + self.export_presets, + self.godot_project, + self.linux_build, + self.windows_build, + self.windows_hosted_export, + ) + ) + for legacy_name in ( + "Himegari.exe", + "Himegari.x86_64", + "Himegari.dll", + "Himegari.csproj", + "Himegari.sln", + "OpenMaidEngine-Himegari", + ): + self.assertNotIn(legacy_name, active_surfaces) def test_build_jobs_are_linux_hosted_read_only_and_target_separate(self) -> None: self.assertRegex(self.text, r"(?m)^permissions:\n contents: read$") @@ -49,8 +92,8 @@ class ReleaseWorkflowTests(unittest.TestCase): def test_windows_artifact_is_archive_plus_structural_evidence(self) -> None: for name in ( - "OpenMaidEngine-Himegari-windows-x64.zip", - "OpenMaidEngine-Himegari-windows-x64.zip.sha256", + "OME-windows-x64.zip", + "OME-windows-x64.zip.sha256", "BUILD-INFO.json", "SHA256SUMS", "WINDOWS-VERIFICATION.json", @@ -66,8 +109,8 @@ class ReleaseWorkflowTests(unittest.TestCase): r"(?m)^ needs:\n - linux-release\n - windows-release$", ) self.assertIn("releases: write", self.publish) - self.assertIn("OpenMaidEngine-Himegari-linux-x64-${{ gitea.sha }}", self.publish) - self.assertIn("OpenMaidEngine-Himegari-windows-x64-${{ gitea.sha }}", self.publish) + self.assertIn("OME-linux-x64-${{ gitea.sha }}", self.publish) + self.assertIn("OME-windows-x64-${{ gitea.sha }}", self.publish) self.assertIn("path: build/release-assets/linux", self.publish) self.assertIn("path: build/release-assets/windows", self.publish) self.assertIn("--linux-artifact-directory build/release-assets/linux", self.publish) diff --git a/tools/validate.py b/tools/validate.py index 1907f05..0ba9984 100644 --- a/tools/validate.py +++ b/tools/validate.py @@ -216,7 +216,7 @@ def build_gate_plan( Gate( "godot-build", "Godot C# build", - ("dotnet", "build", "godot/Himegari.csproj", "--nologo", "--verbosity", "minimal"), + ("dotnet", "build", "godot/OME.csproj", "--nologo", "--verbosity", "minimal"), 300, ), Gate(