From 03c0175e64f099ae8ee039979127b9a1062d6fc8 Mon Sep 17 00:00:00 2001 From: JasonStys Date: Tue, 10 Nov 2026 18:08:50 -0800 Subject: [PATCH 1/3] Add native scene editor with real play replay and durable project workflow --- .github/workflows/ci.yml | 4 +- .github/workflows/codeql.yml | 11 +- .github/workflows/native-app.yml | 63 ++ .gitignore | 3 + CMakeLists.txt | 45 +- README.md | 18 + apps/editor.rc | 31 + apps/editor_files.cpp | 181 +++++ apps/editor_files.hpp | 41 ++ apps/forge2d_editor.cpp | 806 +++++++++++++++++++++++ docs/code-index.md | 321 ++++++++- docs/file-catalog.md | 20 + docs/handbook.md | 5 + docs/images/native-editor-layers.png | Bin 0 -> 98006 bytes docs/images/native-editor-play.png | Bin 0 -> 114113 bytes docs/native-editor.md | 78 +++ docs/reports/native-editor-2026-11-10.md | 47 ++ include/forge2d/editor.hpp | 63 ++ include/forge2d/renderer.hpp | 3 +- scripts/build-native.ps1 | 47 ++ scripts/generate-code-index.mjs | 12 +- scripts/smoke-native.py | 93 +++ scripts/validate-repository.mjs | 4 +- scripts/verify.sh | 4 +- src/editor.cpp | 122 ++++ src/software_renderer.cpp | 25 +- tests/test_editor.cpp | 179 +++++ tests/test_editor_files.cpp | 81 +++ 28 files changed, 2265 insertions(+), 42 deletions(-) create mode 100644 .github/workflows/native-app.yml create mode 100644 apps/editor.rc create mode 100644 apps/editor_files.cpp create mode 100644 apps/editor_files.hpp create mode 100644 apps/forge2d_editor.cpp create mode 100644 docs/images/native-editor-layers.png create mode 100644 docs/images/native-editor-play.png create mode 100644 docs/native-editor.md create mode 100644 docs/reports/native-editor-2026-11-10.md create mode 100644 include/forge2d/editor.hpp create mode 100644 scripts/build-native.ps1 create mode 100644 scripts/smoke-native.py create mode 100644 src/editor.cpp create mode 100644 tests/test_editor.cpp create mode 100644 tests/test_editor_files.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 67050af..4512165 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -111,9 +111,9 @@ jobs: -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - name: Analyze authored targets run: >- - clang-tidy -p build src/collision.cpp src/pathfinding.cpp src/replay.cpp src/scene.cpp + clang-tidy -p build src/editor.cpp src/collision.cpp src/pathfinding.cpp src/replay.cpp src/scene.cpp src/software_renderer.cpp src/world.cpp apps/forge2d_arena.cpp tests/test_main.cpp - benchmarks/benchmark.cpp + tests/test_editor.cpp benchmarks/benchmark.cpp coverage: name: Coverage gate diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 2ef3bcd..92c3f8a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -17,8 +17,13 @@ permissions: jobs: analyze: - name: Analyze C and C++ - runs-on: ubuntu-latest + name: Analyze C and C++ (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] steps: - name: Check out source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -33,3 +38,5 @@ jobs: cmake --build build --parallel 2 - name: Analyze uses: github/codeql-action/analyze@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3; coordinated version + with: + category: /language:c-cpp/os:${{ matrix.os }} diff --git a/.github/workflows/native-app.yml b/.github/workflows/native-app.yml new file mode 100644 index 0000000..b5dda06 --- /dev/null +++ b/.github/workflows/native-app.yml @@ -0,0 +1,63 @@ +# File: native-app.yml +# Purpose: Build and extract-test the actual Windows editor; retain bounded proof, not routine full packages. +name: Native application +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + inputs: + retain_package: + description: Retain the unsigned portable candidate for reviewed main-source distribution + type: boolean + required: false + default: false +permissions: + contents: read +concurrency: + group: native-${{ github.ref }} + cancel-in-progress: true +jobs: + windows: + name: Actual Windows editor and extracted portable package + runs-on: windows-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.14.10" + check-latest: true + - name: Build static-runtime executable and actual core/file tests + shell: pwsh + run: | + $vs = & "${env:ProgramFiles(x86)}/Microsoft Visual Studio/Installer/vswhere.exe" -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath + if (-not $vs -or -not (Test-Path -LiteralPath "$vs/Common7/Tools/VsDevCmd.bat")) { throw 'Reviewed MSVC toolchain unavailable.' } + $command = '"' + $vs + '/Common7/Tools/VsDevCmd.bat" -arch=x64 -host_arch=x64 && pwsh -NoProfile -File scripts/build-native.ps1 -Output release/windows' + & cmd.exe /d /s /c $command + if ($LASTEXITCODE -ne 0) { throw 'Native build/tests failed.' } + - name: Extract package and exercise native play, restart and corrupt-profile recovery + run: python scripts/smoke-native.py release/windows/Forge2DEditor-1.1.0-windows-x64.zip artifacts/native/hosted + - name: Retain bounded synthetic receipts and own-window screenshots + if: always() + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: forge2d-native-proof + path: | + artifacts/native/hosted/*.json + artifacts/native/hosted/*.png + artifacts/native/hosted/*failure.txt + if-no-files-found: warn + retention-days: 1 + - name: Retain full unsigned package only on explicit trusted-main request + if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && inputs.retain_package + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: forge2d-reviewed-portable-candidate + path: | + release/windows/*.zip + release/windows/*.sha256 + if-no-files-found: error + retention-days: 1 diff --git a/.gitignore b/.gitignore index 1fb9db1..c7c05b5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ # File: .gitignore # Purpose: Exclude build products, editor state, generated reports, and local runtime output. .cache/ +.runtime/ +artifacts/ +release/ .idea/ .vs/ .vscode/ diff --git a/CMakeLists.txt b/CMakeLists.txt index c416fe6..a28899f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ # Purpose: Configure the portable engine core, tests, benchmark, sample, and optional SDL3 frontend. cmake_minimum_required(VERSION 3.25) -project(forge2d_engine VERSION 1.0.0 LANGUAGES C CXX) +project(forge2d_engine VERSION 1.1.0 LANGUAGES C CXX) include(CTest) include(GNUInstallDirs) @@ -64,6 +64,7 @@ forge2d_enable_sanitizers(forge2d_platform_c) forge2d_enable_coverage(forge2d_platform_c) add_library(forge2d_core STATIC + src/editor.cpp src/collision.cpp src/pathfinding.cpp src/replay.cpp @@ -87,6 +88,35 @@ forge2d_set_warnings(forge2d_arena) forge2d_enable_sanitizers(forge2d_arena) forge2d_enable_coverage(forge2d_arena) +if(WIN32) + enable_language(RC) + set(FORGE2D_NATIVE_SOURCE "unavailable") + set(FORGE2D_NATIVE_DIRTY "true") + find_package(Git QUIET) + if(GIT_FOUND) + execute_process(COMMAND ${GIT_EXECUTABLE} -c safe.directory=${CMAKE_CURRENT_SOURCE_DIR} + rev-parse HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE native_source OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE native_git_result) + if(native_git_result EQUAL 0 AND native_source MATCHES "^[0-9a-f]+$") + set(FORGE2D_NATIVE_SOURCE "${native_source}") + execute_process(COMMAND ${GIT_EXECUTABLE} -c safe.directory=${CMAKE_CURRENT_SOURCE_DIR} + status --porcelain WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE native_status OUTPUT_STRIP_TRAILING_WHITESPACE) + if(native_status STREQUAL "") + set(FORGE2D_NATIVE_DIRTY "false") + endif() + endif() + endif() + add_executable(Forge2DEditor WIN32 apps/forge2d_editor.cpp apps/editor_files.cpp apps/editor.rc) + target_link_libraries(Forge2DEditor PRIVATE Forge2D::Core comdlg32 gdiplus bcrypt shell32 ole32) + target_compile_definitions(Forge2DEditor PRIVATE UNICODE _UNICODE + FORGE2D_NATIVE_SOURCE="${FORGE2D_NATIVE_SOURCE}" FORGE2D_NATIVE_DIRTY=${FORGE2D_NATIVE_DIRTY}) + forge2d_set_warnings(Forge2DEditor) + add_custom_command(TARGET Forge2DEditor POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_SOURCE_DIR}/assets $/assets) +endif() + if(FORGE2D_BUILD_SDL) include(FetchContent) set(SDL_SHARED OFF CACHE BOOL "" FORCE) @@ -113,6 +143,19 @@ if(FORGE2D_BUILD_TESTS) forge2d_enable_sanitizers(forge2d_tests) forge2d_enable_coverage(forge2d_tests) add_test(NAME forge2d_tests COMMAND forge2d_tests) + add_executable(forge2d_editor_tests tests/test_editor.cpp) + target_link_libraries(forge2d_editor_tests PRIVATE Forge2D::Core) + forge2d_set_warnings(forge2d_editor_tests) + forge2d_enable_sanitizers(forge2d_editor_tests) + forge2d_enable_coverage(forge2d_editor_tests) + add_test(NAME forge2d_editor_tests COMMAND forge2d_editor_tests) + if(WIN32) + add_executable(forge2d_editor_files_tests tests/test_editor_files.cpp apps/editor_files.cpp) + target_link_libraries(forge2d_editor_files_tests PRIVATE Forge2D::Core bcrypt shell32 ole32) + target_compile_definitions(forge2d_editor_files_tests PRIVATE UNICODE _UNICODE) + forge2d_set_warnings(forge2d_editor_files_tests) + add_test(NAME forge2d_editor_files_tests COMMAND forge2d_editor_files_tests) + endif() endif() if(FORGE2D_BUILD_BENCHMARKS) diff --git a/README.md b/README.md index 542bf2b..8cdaa63 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,23 @@ generation-safe entities, sparse-set components, fixed-timestep simulation, spat A* pathfinding, versioned scenes and replays, bounded allocation, software screenshot evidence, an optional SDL3 frontend, and regression budgets. +The **Windows native Forge2D Editor** adds an actual scene-edit/play workflow over that same C++ +engine. Open `Forge2DEditor.exe` from an extracted portable candidate: edit all strict scene fields, +Apply with validation, move the player with focused-canvas keys, Play/Pause/Step, inspect overlap +counts, save an authored project, import recorded inputs and export matching scene/replay/image/ +snapshot evidence. Prepared arena and collision-layer files are normal inputs inside the full app. +The application needs no IDE, compiler, Python, Node or network at runtime. + +Project saves live under the current OS account's local `Forge2DEditor` profile, outside the program +folder. Restart restores the authored scene **paused at tick zero**. Invalid Apply preserves the +previous world; closing warns about unapplied/unsaved edits; a second profile owner is refused. +This is a small, purpose-built editor, not a complete commercial game engine: masks detect AABB +overlaps without physical response, and imported replay files need their matching scene. +See [native usage, fields, limits and build](docs/native-editor.md), +[observed validation](docs/reports/native-editor-2026-11-10.md) and the +[native workflow](.github/workflows/native-app.yml). Created by **Jason Stys**; +[source/contact](https://github.com/JasonStys). + The project is intentionally smaller than a commercial engine. Its goal is to demonstrate memory ownership, data layout, deterministic behavior, parser safety, algorithmic trade-offs, portable build engineering, and honest performance evidence in a codebase a reviewer can understand. @@ -37,6 +54,7 @@ application responsibilities. - Four-neighbor A* with stable tie-breaking and explicit O((V+E) log V) analysis. - Versioned, bounded, strict scene/replay parsers plus a libFuzzer target. - Headless software rendering to portable PPM evidence and an optional SDL3 accelerated frontend. +- C++/Win32 native source editor, fixed-tick play/replay, durable local project and evidence exports. - MSVC, GCC, and Clang builds; warnings-as-errors; ASan/UBSan; fuzz smoke; CodeQL; coverage; packaging; and a non-root headless container. diff --git a/apps/editor.rc b/apps/editor.rc new file mode 100644 index 0000000..912368d --- /dev/null +++ b/apps/editor.rc @@ -0,0 +1,31 @@ +// File: editor.rc +// Purpose: Embed truthful Windows product/author metadata for the portable native editor. +#include +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,1,0,0 + PRODUCTVERSION 1,1,0,0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Jason Stys\0" + VALUE "FileDescription", "Forge2D Editor\0" + VALUE "FileVersion", "1.1.0\0" + VALUE "InternalName", "Forge2DEditor\0" + VALUE "LegalCopyright", "Copyright Jason Stys. MIT license.\0" + VALUE "OriginalFilename", "Forge2DEditor.exe\0" + VALUE "ProductName", "Forge2D Editor\0" + VALUE "ProductVersion", "1.1.0\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/apps/editor_files.cpp b/apps/editor_files.cpp new file mode 100644 index 0000000..f49427d --- /dev/null +++ b/apps/editor_files.cpp @@ -0,0 +1,181 @@ +/** + * File: editor_files.cpp + * Purpose: Keep native project files outside the executable, bound actual reads and atomically + * save. Functions/variables: see docs/code-index.md. Same-OS-user access is trusted; no encryption + * is claimed. + */ +#include "editor_files.hpp" + +#include "forge2d/editor.hpp" + +#include +#include + +#include +#include +#include +#include + +namespace forge2d::desktop { +namespace { +[[noreturn]] void file_error() { + throw std::runtime_error("File unavailable, unsafe, locked, too large, or not writable."); +} + +void regular(HANDLE handle) { + BY_HANDLE_FILE_INFORMATION info{}; + if (handle == INVALID_HANDLE_VALUE || GetFileType(handle) != FILE_TYPE_DISK || + !GetFileInformationByHandle(handle, &info) || info.nNumberOfLinks != 1U || + (info.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) != 0U) { + file_error(); + } +} + +[[nodiscard]] std::wstring random_suffix() { + std::array bytes{}; + if (BCryptGenRandom(nullptr, bytes.data(), static_cast(bytes.size()), + BCRYPT_USE_SYSTEM_PREFERRED_RNG) != 0) { + file_error(); + } + constexpr wchar_t digits[] = L"0123456789abcdef"; + std::wstring result; + for (const auto byte : bytes) { + result += digits[byte >> 4U]; + result += digits[byte & 15U]; + } + return result; +} +} // namespace + +Handle::~Handle() { + if (value_ != INVALID_HANDLE_VALUE && value_ != nullptr) { + CloseHandle(value_); + } +} + +std::string read_text(const std::filesystem::path& path) { + const Handle file{CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, + OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, nullptr)}; + regular(file.get()); + LARGE_INTEGER size{}; + if (!GetFileSizeEx(file.get(), &size) || size.QuadPart < 0 || + size.QuadPart > static_cast(EditorSession::maximum_input_bytes)) { + file_error(); + } + std::string text(static_cast(size.QuadPart), '\0'); + DWORD received{}; + if (!ReadFile(file.get(), text.data(), static_cast(text.size()), &received, nullptr) || + received != text.size()) { + file_error(); + } + char extra{}; + if (!ReadFile(file.get(), &extra, 1, &received, nullptr) || received != 0U) { + file_error(); + } + (void)wide(text); // Reject invalid UTF-8 before it reaches the native text control. + return text; +} + +void atomic_text(const std::filesystem::path& path, std::string_view text) { + if (text.size() > EditorSession::maximum_input_bytes) { + file_error(); + } + const auto attributes = GetFileAttributesW(path.c_str()); + if (attributes != INVALID_FILE_ATTRIBUTES) { + const Handle existing{CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, + OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, nullptr)}; + regular(existing.get()); + } + const auto staging = std::filesystem::path{path.wstring() + L".tmp-" + random_suffix()}; + try { + { + const Handle file{CreateFileW(staging.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, nullptr)}; + regular(file.get()); + DWORD written{}; + if (!WriteFile(file.get(), text.data(), static_cast(text.size()), &written, + nullptr) || + written != text.size() || !FlushFileBuffers(file.get())) { + file_error(); + } + } + if (!MoveFileExW(staging.c_str(), path.c_str(), + MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) { + file_error(); + } + } catch (...) { + DeleteFileW(staging.c_str()); + throw; + } +} + +std::filesystem::path executable_directory() { + std::vector path(32'768U); + const auto length = GetModuleFileNameW(nullptr, path.data(), static_cast(path.size())); + if (length == 0U || length >= path.size()) { + file_error(); + } + return std::filesystem::path{std::wstring{path.data(), length}}.parent_path(); +} + +std::filesystem::path default_profile() { + PWSTR result{}; + if (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &result) != S_OK) { + file_error(); + } + const std::filesystem::path path{result}; + CoTaskMemFree(result); + return path / L"Forge2DEditor"; +} + +void ensure_profile(const std::filesystem::path& path) { + std::filesystem::create_directories(path); + const auto attributes = GetFileAttributesW(path.c_str()); + if (attributes == INVALID_FILE_ATTRIBUTES || + (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0U) { + file_error(); + } +} + +std::wstring wide(std::string_view text) { + if (text.empty()) { + return {}; + } + if (text.size() > EditorSession::maximum_input_bytes) { + file_error(); + } + const auto length = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, text.data(), + static_cast(text.size()), nullptr, 0); + if (length == 0) { + file_error(); + } + std::wstring result(static_cast(length), L'\0'); + if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, text.data(), + static_cast(text.size()), result.data(), length) != length) { + file_error(); + } + return result; +} + +std::string utf8(std::wstring_view text) { + if (text.empty()) { + return {}; + } + if (text.size() > EditorSession::maximum_input_bytes) { + file_error(); + } + const auto length = + WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, text.data(), + static_cast(text.size()), nullptr, 0, nullptr, nullptr); + if (length == 0 || length > static_cast(EditorSession::maximum_input_bytes)) { + file_error(); + } + std::string result(static_cast(length), '\0'); + if (WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, text.data(), + static_cast(text.size()), result.data(), length, nullptr, + nullptr) != length) { + file_error(); + } + return result; +} +} // namespace forge2d::desktop diff --git a/apps/editor_files.hpp b/apps/editor_files.hpp new file mode 100644 index 0000000..fdf4f94 --- /dev/null +++ b/apps/editor_files.hpp @@ -0,0 +1,41 @@ +/** + * File: editor_files.hpp + * Purpose: Declare Windows descriptor-bound scene reads, atomic saves and exclusive profile + * ownership. Symbols, functions and variable locations are listed in docs/code-index.md. + */ +#pragma once + +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include + +#include +#include +#include + +namespace forge2d::desktop { + +/** An owned OS handle is never copied or leaked to a child process. */ +class Handle { + public: + explicit Handle(HANDLE value = INVALID_HANDLE_VALUE) noexcept : value_(value) {} + ~Handle(); + Handle(const Handle&) = delete; + Handle& operator=(const Handle&) = delete; + [[nodiscard]] HANDLE get() const noexcept { + return value_; + } + + private: + HANDLE value_; +}; + +[[nodiscard]] std::string read_text(const std::filesystem::path& path); +void atomic_text(const std::filesystem::path& path, std::string_view text); +[[nodiscard]] std::filesystem::path executable_directory(); +[[nodiscard]] std::filesystem::path default_profile(); +void ensure_profile(const std::filesystem::path& path); +[[nodiscard]] std::wstring wide(std::string_view text); +[[nodiscard]] std::string utf8(std::wstring_view text); + +} // namespace forge2d::desktop diff --git a/apps/forge2d_editor.cpp b/apps/forge2d_editor.cpp new file mode 100644 index 0000000..2714034 --- /dev/null +++ b/apps/forge2d_editor.cpp @@ -0,0 +1,806 @@ +/** + * File: forge2d_editor.cpp + * Purpose: Provide the actual native scene editor, fixed-tick play/replay, durable saves and + * evidence. Functions/classes/important variables: docs/code-index.md. Keyboard input belongs only + * to this window's focused canvas; no global input hooks, network, accounts, plugins or external + * processes. + */ +#include "editor_files.hpp" + +#include "forge2d/editor.hpp" +#include "forge2d/fixed_step.hpp" + +// GDI+ requires the COM IStream/PROPID declarations before its own SDK headers. +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace forge2d::desktop { +namespace { +constexpr int apply_id = 101; +constexpr int play_id = 102; +constexpr int step_id = 103; +constexpr int reset_id = 104; +constexpr int save_id = 105; +constexpr int open_id = 106; +constexpr int replay_id = 107; +constexpr int export_id = 108; +constexpr int arena_id = 109; +constexpr int layers_id = 110; +constexpr int help_id = 111; +constexpr int quit_id = 112; +constexpr int text_id = 120; +constexpr UINT_PTR frame_timer = 1U; +constexpr UINT_PTR acceptance_timer = 2U; +constexpr wchar_t help_text[] = + L"Forge2D Editor 1.1.0 | Created by Jason Stys\n\n" + L"1. Open a scene or choose a prepared example. Edit the strict scene text; Apply validates " + L"all " + L"fields before replacing the running world. Invalid edits preserve the applied scene.\n" + L"2. Click the canvas. WASD/arrow keys control the player, Space records action. Play advances " + L"60 fixed ticks/second; Step advances once. Reset returns to the authored scene.\n" + L"3. Save project stores the applied scene in your local profile. Unapplied edits are not " + L"saved. " + L"Import replay plays recorded inputs against the currently applied scene. Export evidence " + L"writes that scene, its replay, a PPM image and numeric snapshot together.\n\n" + L"Scene row v2: entity NAME X Y VX VY HALF_W HALF_H RGBA LAYER PLAYER CATEGORY MASK. " + L"Integers only; category is one positive bit. Mask zero disables matching. Bounds must " + L"contain " + L"every body. Native limits: 1 MiB input, 1,000 entities, 36,000 frames at 60 Hz.\n\n" + L"AABB masks report candidate overlaps; they do not provide physical collision response. " + L"Unrecorded real-time scheduling drops excess ticks instead of accumulating lag. Exported " + L"replays require the matching scene. Local files are plaintext under your OS account; do not " + L"put secrets in scene names. Closing releases only this application's profile lock.\n\n" + L"Contact: github.com/JasonStys | Windows portable app; unsigned, no installer required."; + +/** Retrieve only this editor's text; size validation precedes allocation and UTF-8 conversion. */ +[[nodiscard]] std::string editor_text(HWND control) { + const auto count = GetWindowTextLengthW(control); + if (count < 0 || count > static_cast(EditorSession::maximum_input_bytes)) { + throw std::invalid_argument("Scene text exceeds the 1 MiB native editor limit."); + } + std::wstring text(static_cast(count) + 1U, L'\0'); + const auto received = GetWindowTextW(control, text.data(), count + 1); + text.resize(static_cast(received)); + auto encoded = utf8(text); + std::string portable; + portable.reserve(encoded.size()); + for (std::size_t index = 0; index < encoded.size(); ++index) { + if (encoded[index] == '\r' && index + 1U < encoded.size() && encoded[index + 1U] == '\n') { + continue; + } + portable += encoded[index]; + } + return portable; +} + +[[nodiscard]] std::filesystem::path choose_file(HWND owner, bool save, const wchar_t* filter) { + std::array path{}; + OPENFILENAMEW dialog{}; + dialog.lStructSize = sizeof(dialog); + dialog.hwndOwner = owner; + dialog.lpstrFilter = filter; + dialog.lpstrFile = path.data(); + dialog.nMaxFile = static_cast(path.size()); + dialog.Flags = + OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | (save ? OFN_OVERWRITEPROMPT : OFN_FILEMUSTEXIST); + dialog.lpstrDefExt = L"scene"; + if ((save ? GetSaveFileNameW(&dialog) : GetOpenFileNameW(&dialog)) == FALSE) { + return {}; + } + return std::filesystem::path{path.data()}; +} + +void require(bool condition, const char* message) { + if (!condition) { + throw std::runtime_error(message); + } +} + +/** Capture this application's owned visible window only, never the desktop or another process. */ +void screenshot(HWND window, const std::filesystem::path& destination) { + RECT bounds{}; + GetWindowRect(window, &bounds); + const auto width = bounds.right - bounds.left; + const auto height = bounds.bottom - bounds.top; + const auto screen = GetDC(window); + const auto memory = CreateCompatibleDC(screen); + const auto bitmap = CreateCompatibleBitmap(screen, width, height); + const auto previous = SelectObject(memory, bitmap); + const auto painted = PrintWindow(window, memory, 2U); + SelectObject(memory, previous); + DeleteDC(memory); + ReleaseDC(window, screen); + if (painted == FALSE) { + DeleteObject(bitmap); + throw std::runtime_error("Owned window screenshot was unavailable."); + } + Gdiplus::GdiplusStartupInput startup; + ULONG_PTR token{}; + require(Gdiplus::GdiplusStartup(&token, &startup, nullptr) == Gdiplus::Ok, + "Screenshot encoder unavailable."); + bool saved{}; + { + // The PNG encoder has a stable system CLSID; it does not load an application plugin. + const CLSID encoder{0x557cf406, 0x1a04, 0x11d3, {0x9a, 0x73, 0, 0, 0xf8, 0x1e, 0xf3, 0x2e}}; + Gdiplus::Bitmap image{bitmap, nullptr}; + saved = image.Save(destination.c_str(), &encoder, nullptr) == Gdiplus::Ok; + } + Gdiplus::GdiplusShutdown(token); + DeleteObject(bitmap); + require(saved, "Screenshot could not be saved."); +} + +/** Main-window state. Session state, disk profile and visible source buffer remain separate. */ +class Application { + public: + Application(std::filesystem::path profile, std::filesystem::path acceptance, int phase) + : profile_(std::move(profile)), acceptance_(std::move(acceptance)), phase_(phase), + owner_(CreateFileW((profile_ / L"owner.lock").c_str(), GENERIC_READ | GENERIC_WRITE, 0, + nullptr, OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OPEN_REPARSE_POINT, nullptr)) { + require(owner_.get() != INVALID_HANDLE_VALUE, + "This profile is already open or unavailable."); + BY_HANDLE_FILE_INFORMATION info{}; + require(GetFileInformationByHandle(owner_.get(), &info) != FALSE && + info.nNumberOfLinks == 1U && + (info.dwFileAttributes & + (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) == 0U, + "Unsafe profile lock."); + const auto defaults = read_text(executable_directory() / L"assets" / L"arena.scene"); + session_ = std::make_unique(defaults); + const auto saved = profile_ / L"project.scene"; + if (std::filesystem::exists(saved)) { + try { + session_->apply_scene(read_text(saved)); + } catch (const std::exception&) { + load_error_ = + true; // Preserve corrupt input; save requires an explicit new decision. + } + } + } + + int run(HINSTANCE instance, int show) { + WNDCLASSW main_class{}; + main_class.hInstance = instance; + main_class.lpfnWndProc = procedure; + main_class.lpszClassName = L"Forge2DEditorWindow"; + main_class.hCursor = LoadCursorW(nullptr, IDC_ARROW); + main_class.hbrBackground = reinterpret_cast(COLOR_BTNFACE + 1); + require(RegisterClassW(&main_class) != 0U, "Cannot register editor window."); + WNDCLASSW canvas_class = main_class; + canvas_class.lpfnWndProc = canvas_procedure; + canvas_class.lpszClassName = L"Forge2DEditorCanvas"; + canvas_class.hbrBackground = nullptr; + require(RegisterClassW(&canvas_class) != 0U, "Cannot register canvas."); + window_ = CreateWindowExW(0, main_class.lpszClassName, L"Forge2D Editor 1.1.0 - Jason Stys", + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, + CW_USEDEFAULT, 1240, 850, nullptr, nullptr, instance, this); + require(window_ != nullptr, "Cannot create editor window."); + ShowWindow(window_, show); + UpdateWindow(window_); + if (!acceptance_.empty()) { + SetTimer(window_, acceptance_timer, 200U, nullptr); + } + MSG message{}; + while (GetMessageW(&message, nullptr, 0, 0) > 0) { + TranslateMessage(&message); + DispatchMessageW(&message); + } + return exit_code_; + } + + private: + static LRESULT CALLBACK procedure(HWND window, UINT message, WPARAM wparam, LPARAM lparam) { + auto* app = reinterpret_cast(GetWindowLongPtrW(window, GWLP_USERDATA)); + if (message == WM_NCCREATE) { + const auto* create = reinterpret_cast(lparam); + app = static_cast(create->lpCreateParams); + app->window_ = window; + SetWindowLongPtrW(window, GWLP_USERDATA, reinterpret_cast(app)); + } + if (app != nullptr) { + try { + return app->message(message, wparam, lparam); + } catch (const std::exception& error) { + app->session_->pause(); + app->notice_ = wide(error.what()); + if (!app->acceptance_.empty()) { + app->exit_code_ = 2; + atomic_text(app->acceptance_ / L"failure.txt", error.what()); + DestroyWindow(window); + } else { + MessageBoxW(window, app->notice_.c_str(), L"Forge2D - input not applied", + MB_OK | MB_ICONWARNING); + app->update_status(); + } + return 0; + } + } + return DefWindowProcW(window, message, wparam, lparam); + } + + static LRESULT CALLBACK canvas_procedure(HWND window, UINT message, WPARAM wparam, + LPARAM lparam) { + auto* app = reinterpret_cast(GetWindowLongPtrW(window, GWLP_USERDATA)); + if (message == WM_NCCREATE) { + const auto* create = reinterpret_cast(lparam); + app = static_cast(create->lpCreateParams); + SetWindowLongPtrW(window, GWLP_USERDATA, reinterpret_cast(app)); + } + if (app == nullptr) { + return DefWindowProcW(window, message, wparam, lparam); + } + if (message == WM_LBUTTONDOWN) { + SetFocus(window); + return 0; + } + if (message == WM_KILLFOCUS) { + app->keys_.fill(false); + } + if ((message == WM_KEYDOWN || message == WM_KEYUP) && wparam < app->keys_.size()) { + app->keys_[wparam] = message == WM_KEYDOWN; + return 0; + } + if (message == WM_PAINT) { + try { + app->paint_canvas(window); + } catch (...) { + app->session_->pause(); + } + return 0; + } + return DefWindowProcW(window, message, wparam, lparam); + } + + LRESULT message(UINT kind, WPARAM wparam, LPARAM lparam) { + switch (kind) { + case WM_CREATE: + create_controls(); + return 0; + case WM_SIZE: + layout(); + return 0; + case WM_GETMINMAXINFO: { + auto* size = reinterpret_cast(lparam); + size->ptMinTrackSize = POINT{900, 650}; + return 0; + } + case WM_COMMAND: + if (LOWORD(wparam) == text_id && HIWORD(wparam) == EN_CHANGE && !setting_text_) { + unapplied_ = true; + update_status(); + } else if (HIWORD(wparam) == 0U) { + command(LOWORD(wparam)); + } + return 0; + case WM_TIMER: + if (wparam == acceptance_timer) { + KillTimer(window_, acceptance_timer); + acceptance(); + } else if (wparam == frame_timer) { + const auto now = std::chrono::steady_clock::now(); + const auto ticks = clock_.consume(now - last_frame_); + last_frame_ = now; + const auto previous_tick = session_->world().tick(); + for (std::size_t tick = 0; tick < ticks; ++tick) { + session_->advance(input()); + } + if (session_->world().tick() != previous_tick) { + update_status(); + } + } + return 0; + case WM_CLOSE: + if (acceptance_.empty() && (unapplied_ || unsaved_) && + MessageBoxW(window_, L"Unapplied or unsaved edits will be discarded. Close?", + L"Forge2D - preserve your work", + MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING) != IDYES) { + return 0; + } + DestroyWindow(window_); + return 0; + case WM_DESTROY: + KillTimer(window_, frame_timer); + PostQuitMessage(0); + return 0; + default: + return DefWindowProcW(window_, kind, wparam, lparam); + } + } + + HWND child(const wchar_t* type, const wchar_t* text, DWORD style, int id) { + const auto control = CreateWindowExW( + type == std::wstring_view{L"EDIT"} ? WS_EX_CLIENTEDGE : 0, type, text, + WS_CHILD | WS_VISIBLE | style, 0, 0, 1, 1, window_, + reinterpret_cast(static_cast(id)), GetModuleHandleW(nullptr), nullptr); + require(control != nullptr, "Cannot create editor control."); + SendMessageW(control, WM_SETFONT, + reinterpret_cast(GetStockObject(DEFAULT_GUI_FONT)), TRUE); + return control; + } + + void create_controls() { + const auto menu = CreateMenu(); + const auto file = CreatePopupMenu(); + AppendMenuW(file, MF_STRING, open_id, L"Open scene..."); + AppendMenuW(file, MF_STRING, save_id, L"Save applied project to profile"); + AppendMenuW(file, MF_STRING, replay_id, L"Import replay..."); + AppendMenuW(file, MF_STRING, export_id, L"Export evidence bundle..."); + AppendMenuW(file, MF_STRING, quit_id, L"Exit"); + AppendMenuW(menu, MF_POPUP, reinterpret_cast(file), L"File"); + const auto examples = CreatePopupMenu(); + AppendMenuW(examples, MF_STRING, arena_id, L"Prepared arena"); + AppendMenuW(examples, MF_STRING, layers_id, L"Collision layers"); + AppendMenuW(menu, MF_POPUP, reinterpret_cast(examples), L"Prepared data"); + AppendMenuW(menu, MF_STRING, help_id, L"Help / About"); + SetMenu(window_, menu); + const std::array, 6> buttons{ + {{apply_id, L"Apply scene"}, + {play_id, L"Play / Pause"}, + {step_id, L"Step"}, + {reset_id, L"Reset"}, + {save_id, L"Save project"}, + {export_id, L"Export evidence"}}}; + for (const auto& [id, label] : buttons) { + buttons_.push_back(child(L"BUTTON", label, WS_TABSTOP | BS_PUSHBUTTON, id)); + } + heading_ = + child(L"STATIC", L"Applied world | click here, then WASD / arrows / Space", 0, 0); + source_label_ = + child(L"STATIC", L"Scene source | edit, then Apply (all fields are editable)", 0, 0); + source_ = child(L"EDIT", L"", + ES_MULTILINE | ES_WANTRETURN | ES_AUTOVSCROLL | ES_AUTOHSCROLL | + WS_VSCROLL | WS_HSCROLL | WS_TABSTOP, + text_id); + SendMessageW(source_, EM_SETLIMITTEXT, EditorSession::maximum_input_bytes, 0); + SendMessageW(source_, WM_SETFONT, reinterpret_cast(GetStockObject(ANSI_FIXED_FONT)), + TRUE); + canvas_ = CreateWindowExW(WS_EX_CLIENTEDGE, L"Forge2DEditorCanvas", L"Actual engine canvas", + WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 0, 1, 1, window_, nullptr, + GetModuleHandleW(nullptr), this); + require(canvas_ != nullptr, "Cannot create engine canvas."); + instructions_ = + child(L"STATIC", + L"Save keeps the applied authored scene; replay records actual tick inputs.\r\n" + L"Collision masks detect overlaps, not physical response. File > Export evidence " + L"includes the matching scene.\r\n" + L"Local OS profile, no network. Created by Jason Stys | github.com/JasonStys | " + L"Help / About explains fields.", + 0, 0); + status_ = child(L"STATIC", L"", SS_LEFT, 0); + set_source(session_->scene_text()); + if (load_error_) { + notice_ = L"Saved project invalid: preserved on disk; working from prepared scene. " + L"Export recovery before overwriting."; + } else if (!std::filesystem::exists(profile_ / L"project.scene")) { + notice_ = L"First use: choose prepared data, edit and Apply, click canvas, Play. Save " + L"project persists it."; + } + last_frame_ = std::chrono::steady_clock::now(); + SetTimer(window_, frame_timer, 16U, nullptr); + layout(); + update_status(); + } + + void layout() { + RECT bounds{}; + GetClientRect(window_, &bounds); + const auto width = std::max(880L, bounds.right); + const auto height = std::max(580L, bounds.bottom); + const auto split = width * 54 / 100; + for (std::size_t index = 0; index < buttons_.size(); ++index) { + MoveWindow(buttons_[index], 12 + static_cast(index) * 137, 10, 129, 32, TRUE); + } + MoveWindow(heading_, 12, 53, split - 24, 24, TRUE); + MoveWindow(source_label_, split + 8, 53, width - split - 20, 24, TRUE); + MoveWindow(canvas_, 12, 81, split - 24, height - 216, TRUE); + MoveWindow(source_, split + 8, 81, width - split - 20, height - 216, TRUE); + MoveWindow(status_, 12, height - 125, width - 24, 53, TRUE); + MoveWindow(instructions_, 12, height - 66, width - 24, 62, TRUE); + } + + void set_source(std::string_view text) { + // A native multiline EDIT requires CRLF; scene serialization deliberately remains portable + // LF. + std::string displayed; + displayed.reserve(text.size() + + static_cast(std::count(text.begin(), text.end(), '\n'))); + for (const auto character : text) { + if (character == '\r') { + continue; + } + if (character == '\n') { + displayed += '\r'; + } + displayed += character; + } + setting_text_ = true; + require(SetWindowTextW(source_, wide(displayed).c_str()) != FALSE, + "Cannot display scene source."); + setting_text_ = false; + unapplied_ = false; + } + + [[nodiscard]] InputFrame input() const { + const auto horizontal = static_cast(keys_[VK_RIGHT] || keys_['D']) - + static_cast(keys_[VK_LEFT] || keys_['A']); + const auto vertical = static_cast(keys_[VK_DOWN] || keys_['S']) - + static_cast(keys_[VK_UP] || keys_['W']); + return {static_cast(horizontal), static_cast(vertical), + keys_[VK_SPACE]}; + } + + void update_status() { + const auto& world = session_->world(); + std::wostringstream text; + text << (session_->playing() ? L"PLAYING" : L"PAUSED") << L" | tick " << world.tick() + << L" | entities " << world.entity_count() << L" | overlap pairs " + << world.collision_pairs().size() << L" | recorded " + << session_->recording().frames.size() << L"/36000" + << (session_->reviewing_replay() ? L" | imported replay" : L" | live input") + << (unapplied_ ? L" | UNAPPLIED EDITS" : L"") << (unsaved_ ? L" | UNSAVED" : L"") + << L" | dropped wall ticks " << clock_.dropped_ticks() << L"\r\n" + << notice_; + SetWindowTextW(status_, text.str().c_str()); + InvalidateRect(canvas_, nullptr, FALSE); + } + + void command(int id) { + notice_.clear(); + if (id == apply_id) { + session_->apply_scene(editor_text(source_)); + unapplied_ = false; + unsaved_ = true; + } else if (id == play_id) { + if (session_->playing()) { + session_->pause(); + } else { + session_->play(); + SetFocus(canvas_); + } + } else if (id == step_id) { + session_->pause(); + session_->step(input()); + } else if (id == reset_id) { + session_->reset(); + } else if (id == save_id) { + require(!unapplied_, "Apply or discard the pending source edits before saving."); + if (load_error_ && acceptance_.empty() && + MessageBoxW(window_, + L"The saved project was invalid and has been preserved. Replace it " + L"with the applied scene?", + L"Confirm project replacement", + MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING) != IDYES) { + return; + } + atomic_text(profile_ / L"project.scene", session_->scene_text()); + unsaved_ = false; + load_error_ = false; + notice_ = L"Applied project saved in your OS-local profile. Running state is not " + L"auto-resumed."; + } else if (id == open_id || id == arena_id || id == layers_id) { + if ((unapplied_ || unsaved_) && acceptance_.empty() && + MessageBoxW( + window_, + L"Replace the editor buffer and applied scene, discarding unsaved edits?", + L"Open scene", MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING) != IDYES) { + return; + } + auto path = + id == open_id + ? choose_file(window_, false, L"Forge2D scene\0*.scene\0All files\0*.*\0") + : executable_directory() / L"assets" / + (id == arena_id ? L"arena.scene" : L"collision-layers.scene"); + if (!path.empty()) { + session_->apply_scene(read_text(path)); + set_source(session_->scene_text()); + unsaved_ = true; + } + } else if (id == replay_id) { + const auto path = + choose_file(window_, false, L"Forge2D replay\0*.replay\0All files\0*.*\0"); + if (!path.empty()) { + session_->load_replay(read_text(path)); + notice_ = L"Replay loaded against the applied scene. Play or Step consumes its " + L"recorded inputs."; + } + } else if (id == export_id) { + const auto path = choose_file(window_, true, L"Evidence bundle base\0*.scene\0"); + if (!path.empty()) { + const auto directory = path.parent_path() / (path.stem().wstring() + L".evidence"); + export_bundle(directory); + notice_ = L"Evidence folder created; existing folders are never overwritten."; + } + } else if (id == help_id) { + MessageBoxW(window_, help_text, L"Forge2D - how this editor works", + MB_OK | MB_ICONINFORMATION); + } else if (id == quit_id) { + SendMessageW(window_, WM_CLOSE, 0, 0); + return; + } + update_status(); + } + + void export_bundle(const std::filesystem::path& path) const { + require(std::filesystem::create_directory(path), + "Choose a new evidence folder; existing exports are preserved."); + atomic_text(path / L"scene.scene", session_->scene_text()); + atomic_text(path / L"inputs.replay", session_->replay_text()); + const auto image = session_->image(640U, 640U); + image.write_ppm(path / L"frame.ppm"); + std::ostringstream csv; + csv << "entity_id,player,x,y,vx,vy,category,mask\n"; + for (const auto& entity : session_->world().snapshot()) { + csv << entity.entity.packed() << ',' << static_cast(entity.player) << ',' + << entity.transform.position.x << ',' << entity.transform.position.y << ',' + << entity.body.velocity.x << ',' << entity.body.velocity.y << ',' + << entity.body.filter.category << ',' << entity.body.filter.mask << '\n'; + } + atomic_text(path / L"snapshot.csv", csv.str()); + std::ostringstream report; + report << "{\"schema\":1,\"version\":\"" << FORGE2D_VERSION + << "\",\"tick\":" << session_->world().tick() << ",\"stateHash\":\"" + << session_->world().state_hash() << "\",\"pixelHash\":\"" << image.pixel_hash() + << "\",\"overlapPairs\":" << session_->world().collision_pairs().size() + << ",\"recordedFrames\":" << session_->recording().frames.size() + << ",\"author\":\"Jason Stys\"}\n"; + atomic_text(path / L"summary.json", report.str()); + } + + void paint_canvas(HWND canvas) { + PAINTSTRUCT paint{}; + const auto dc = BeginPaint(canvas, &paint); + RECT bounds{}; + GetClientRect(canvas, &bounds); + if (bounds.right > 0 && bounds.bottom > 0) { + const auto image = session_->image(640U, 640U); + std::vector pixels; + pixels.reserve(image.pixels().size()); + for (const auto rgba : image.pixels()) { + pixels.push_back(rgba >> 8U); + } + BITMAPINFO info{}; + info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + info.bmiHeader.biWidth = 640; + info.bmiHeader.biHeight = -640; + info.bmiHeader.biPlanes = 1; + info.bmiHeader.biBitCount = 32; + info.bmiHeader.biCompression = BI_RGB; + StretchDIBits(dc, 0, 0, bounds.right, bounds.bottom, 0, 0, 640, 640, pixels.data(), + &info, DIB_RGB_COLORS, SRCCOPY); + } + EndPaint(canvas, &paint); + } + + /** Event-dispatched synthetic acceptance exercises this same visible executable and handlers. + */ + void acceptance() { + require(IsWindowVisible(window_) != FALSE && IsWindowVisible(canvas_) != FALSE, + "Native editor window is not visible."); + if (phase_ == 1) { + if (acceptance_play_pending_) { + if (session_->playing() && GetTickCount64() - acceptance_play_started_ < 2'000U) { + SetTimer(window_, acceptance_timer, 16U, nullptr); + return; + } + require(!session_->playing() && session_->world().tick() == 3U && + session_->world().state_hash() == acceptance_replay_hash_, + "Native Play timer did not complete the three-frame imported replay."); + finish_acceptance(); + return; + } + command(arena_id); + require(SendMessageW(source_, EM_GETLINECOUNT, 0, 0) >= 10, + "Native source control did not display the actual multiline scene."); + const Handle duplicate{CreateFileW((profile_ / L"owner.lock").c_str(), GENERIC_READ, 0, + nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, + nullptr)}; + require(duplicate.get() == INVALID_HANDLE_VALUE, + "Profile owner lock was not exclusive."); + auto authored = editor_text(source_); + const auto location = authored.find("750 750"); + require(location != std::string::npos, "Prepared scene coordinate missing."); + authored.replace(location, 7, "1100 900"); + SetWindowTextW(source_, wide(authored).c_str()); + SendMessageW(window_, WM_COMMAND, apply_id, 0); + SendMessageW(window_, WM_COMMAND, save_id, 0); + require(!unapplied_ && !unsaved_, + "Applied scene not saved through the actual handler."); + const auto saved = read_text(profile_ / L"project.scene"); + const auto before = session_->world().state_hash(); + SetWindowTextW(source_, L"FORGE2D_SCENE invalid"); + bool refused{}; + try { + command(apply_id); + } catch (const std::exception&) { + refused = true; + } + require(refused && session_->world().state_hash() == before && + read_text(profile_ / L"project.scene") == saved, + "Invalid scene changed applied world or saved file."); + set_source(saved); + SetFocus(canvas_); + SendMessageW(canvas_, WM_KEYDOWN, VK_RIGHT, 0); + for (int tick = 0; tick < 3; ++tick) { + SendMessageW(window_, WM_COMMAND, step_id, 0); + } + SendMessageW(canvas_, WM_KEYUP, VK_RIGHT, 0); + const auto snapshot = session_->world().snapshot(); + const auto player = std::find_if(snapshot.begin(), snapshot.end(), + [](const auto& entity) { return entity.player; }); + require(player != snapshot.end() && player->transform.position == Vec2i{1520, 900}, + "Actual engine did not execute the three captured right inputs."); + const auto hash = session_->world().state_hash(); + const auto replay = session_->replay_text(); + export_bundle(acceptance_ / L"evidence"); + const auto initial = World::from_scene( + parse_scene(read_text(acceptance_ / L"evidence" / L"scene.scene"))); + require(run_replay(initial, parse_replay(read_text(acceptance_ / L"evidence" / + L"inputs.replay"))) == hash, + "Exported scene/replay does not independently reproduce the state."); + session_->load_replay(replay); + acceptance_replay_hash_ = hash; + acceptance_play_pending_ = true; + acceptance_play_started_ = GetTickCount64(); + SendMessageW(window_, WM_COMMAND, play_id, 0); + SetTimer(window_, acceptance_timer, 16U, nullptr); + return; + } else if (phase_ == 2) { + require(!load_error_, "Saved project did not restore."); + const auto snapshot = session_->world().snapshot(); + const auto player = std::find_if(snapshot.begin(), snapshot.end(), + [](const auto& entity) { return entity.player; }); + require(player != snapshot.end() && player->transform.position == Vec2i{1100, 900} && + session_->world().tick() == 0U && !session_->playing(), + "Restart did not restore authored coordinates paused at tick zero."); + atomic_text(acceptance_ / L"phase-2.json", + "{\"schema\":1,\"version\":\"1.1.0\",\"restoredAuthoredScene\":true," + "\"tick\":0,\"playing\":false}\n"); + } else { + require(load_error_ && !session_->playing() && + read_text(profile_ / L"project.scene") == "invalid saved scene\n" && + notice_.find(L"preserved on disk") != std::wstring::npos, + "Corrupt saved project was reset or not visibly identified."); + atomic_text(acceptance_ / L"phase-3.json", + "{\"schema\":1,\"version\":\"1.1.0\",\"corruptProjectPreserved\":true," + "\"visibleRecoveryNotice\":true,\"preparedWorkingCopy\":true}\n"); + } + unapplied_ = false; + unsaved_ = false; + SendMessageW(window_, WM_COMMAND, quit_id, 0); + } + + void finish_acceptance() { + notice_ = L"Acceptance: applied custom coordinates, refused invalid input, saved, played " + L"three inputs and verified exported replay."; + update_status(); + UpdateWindow(canvas_); + UpdateWindow(window_); + screenshot(window_, acceptance_ / L"editor-play.png"); + command(layers_id); + notice_ = L"Prepared collision-layer scene: category/mask fields are editable in the same " + L"application."; + update_status(); + UpdateWindow(canvas_); + screenshot(window_, acceptance_ / L"editor-layers.png"); + bool overwrite_refused{}; + try { + export_bundle(acceptance_ / L"evidence"); + } catch (const std::exception&) { + overwrite_refused = true; + } + require(overwrite_refused && read_text(acceptance_ / L"evidence" / L"scene.scene") == + read_text(profile_ / L"project.scene"), + "Existing export was overwritten."); + set_source("FORGE2D_SCENE 2\nbounds 0 0 1000 1000\nentities 0\n"); + command(apply_id); + command(step_id); + require(session_->world().entity_count() == 0U && session_->world().tick() == 1U, + "Empty scene could not be applied and stepped through the native controls."); + std::ostringstream receipt; + receipt + << "{\"schema\":1,\"version\":\"1.1.0\",\"visibleWindow\":true,\"customScene\":true," + "\"invalidPreserved\":true,\"realInputs\":3,\"player\":[1520,900]," + "\"exportReplayVerified\":true,\"nativeHandlers\":true,\"nativePlayTimer\":true," + "\"profileLockExclusive\":true,\"multilineSource\":true,\"exportOverwriteRefused\":" + "true,\"emptyScene\":true,\"source\":\"" + << FORGE2D_NATIVE_SOURCE + << "\",\"sourceDirty\":" << (FORGE2D_NATIVE_DIRTY ? "true" : "false") << "}\n"; + atomic_text(acceptance_ / L"phase-1.json", receipt.str()); + unapplied_ = false; + unsaved_ = false; + SendMessageW(window_, WM_COMMAND, quit_id, 0); + } + + std::filesystem::path profile_; + std::filesystem::path acceptance_; + int phase_{}; + Handle owner_; + std::unique_ptr session_; + HWND window_{}; + HWND canvas_{}; + HWND source_{}; + HWND heading_{}; + HWND source_label_{}; + HWND instructions_{}; + HWND status_{}; + std::vector buttons_; + std::array keys_{}; + bool setting_text_{}; + bool unapplied_{}; + bool unsaved_{}; + bool load_error_{}; + int exit_code_{}; + bool acceptance_play_pending_{}; + ULONGLONG acceptance_play_started_{}; + std::uint64_t acceptance_replay_hash_{}; + std::wstring notice_; + FixedStepClock clock_{std::chrono::nanoseconds{1'000'000'000 / 60}}; + std::chrono::steady_clock::time_point last_frame_{}; +}; +} // namespace +} // namespace forge2d::desktop + +/** No user-selected arguments are executed. Acceptance roots require an explicit private marker. */ +int WINAPI wWinMain(HINSTANCE instance, HINSTANCE, PWSTR, int show) { + using namespace forge2d::desktop; + std::filesystem::path acceptance; + try { + int count{}; + auto** arguments = CommandLineToArgvW(GetCommandLineW(), &count); + require(arguments != nullptr, "Cannot read application arguments."); + std::filesystem::path profile; + int phase{}; + if (count == 1) { + profile = default_profile(); + } else if (count == 5 && std::wstring_view{arguments[1]} == L"--acceptance-root" && + std::wstring_view{arguments[3]} == L"--acceptance-phase") { + std::array enabled{}; + require(GetEnvironmentVariableW(L"FORGE2D_ACCEPTANCE", enabled.data(), + static_cast(enabled.size())) == 1U && + enabled[0] == L'1', + "Acceptance mode is not enabled."); + acceptance = std::filesystem::absolute(arguments[2]); + require(read_text(acceptance / L"acceptance.marker") == "forge2d-owned-native-test\n", + "Acceptance root marker is missing."); + const std::wstring_view choice{arguments[4]}; + require(choice == L"1" || choice == L"2" || choice == L"3", + "Invalid acceptance phase."); + phase = choice == L"1" ? 1 : (choice == L"2" ? 2 : 3); + profile = acceptance / L"profile"; + } else { + LocalFree(arguments); + throw std::invalid_argument( + "This application does not accept arbitrary command-line arguments."); + } + LocalFree(arguments); + ensure_profile(profile); + Application app{profile, acceptance, phase}; + return app.run(instance, show); + } catch (const std::exception& error) { + if (acceptance.empty()) { + MessageBoxW(nullptr, wide(error.what()).c_str(), L"Forge2D Editor could not start", + MB_OK | MB_ICONERROR); + } else { + try { + atomic_text(acceptance / L"startup-failure.txt", error.what()); + } catch (...) { + // A failure cannot justify writing elsewhere or displaying a modal test dialog. + } + } + return 2; + } +} diff --git a/docs/code-index.md b/docs/code-index.md index 276dfec..f75c932 100644 --- a/docs/code-index.md +++ b/docs/code-index.md @@ -3,6 +3,53 @@ Generated by `scripts/generate-code-index.mjs`. Source headers point here for exact declaration locations. Regenerate after authored source changes. +## `apps/editor_files.cpp` + +- Line 21: `file_error` +- Line 25: `regular` +- Line 26: `info` +- Line 34: `random_suffix` +- Line 35: `bytes` +- Line 40: `digits` +- Line 50: `Handle::~Handle` +- Line 56: `read_text` +- Line 60: `size` +- Line 65: `text` +- Line 66: `received` +- Line 71: `extra` +- Line 79: `atomic_text` +- Line 83: `attributes` +- Line 89: `staging` +- Line 95: `written` +- Line 112: `executable_directory` +- Line 113: `path` +- Line 114: `length` +- Line 121: `default_profile` +- Line 122: `result` +- Line 131: `ensure_profile` +- Line 133: `attributes` +- Line 140: `wide` +- Line 147: `length` +- Line 152: `result` +- Line 160: `utf8` +- Line 167: `length` +- Line 173: `result` + +## `apps/editor_files.hpp` + +- Line 19: `Handle` +- Line 21: `Handle` +- Line 23: `Handle` +- Line 24: `operator=` +- Line 25: `get` +- Line 33: `read_text` +- Line 34: `atomic_text` +- Line 35: `executable_directory` +- Line 36: `default_profile` +- Line 37: `ensure_profile` +- Line 38: `wide` +- Line 39: `utf8` + ## `apps/forge2d_arena.cpp` - Line 25: `read_text` @@ -39,6 +86,134 @@ declaration locations. Regenerate after authored source changes. - Line 31: `input_frame` - Line 33: `now` +## `apps/forge2d_editor.cpp` + +- Line 32: `apply_id` +- Line 33: `play_id` +- Line 34: `step_id` +- Line 35: `reset_id` +- Line 36: `save_id` +- Line 37: `open_id` +- Line 38: `replay_id` +- Line 39: `export_id` +- Line 40: `arena_id` +- Line 41: `layers_id` +- Line 42: `help_id` +- Line 43: `quit_id` +- Line 44: `text_id` +- Line 45: `frame_timer` +- Line 46: `acceptance_timer` +- Line 47: `help_text` +- Line 69: `editor_text` +- Line 70: `count` +- Line 74: `text` +- Line 75: `received` +- Line 77: `encoded` +- Line 89: `choose_file` +- Line 91: `dialog` +- Line 106: `require` +- Line 113: `screenshot` +- Line 114: `bounds` +- Line 116: `width` +- Line 117: `height` +- Line 118: `screen` +- Line 119: `memory` +- Line 120: `bitmap` +- Line 121: `previous` +- Line 122: `painted` +- Line 131: `token` +- Line 134: `saved` +- Line 138: `image` +- Line 147: `Application` +- Line 149: `Application` +- Line 150: `profile_` +- Line 156: `info` +- Line 162: `defaults` +- Line 164: `saved` +- Line 175: `run` +- Line 176: `main_class` +- Line 197: `message` +- Line 206: `procedure` +- Line 207: `app` +- Line 209: `create` +- Line 235: `canvas_procedure` +- Line 237: `app` +- Line 239: `create` +- Line 268: `message` +- Line 277: `size` +- Line 294: `now` +- Line 295: `ticks` +- Line 297: `previous_tick` +- Line 324: `child` +- Line 325: `control` +- Line 335: `create_controls` +- Line 336: `menu` +- Line 337: `file` +- Line 344: `examples` +- Line 398: `layout` +- Line 399: `bounds` +- Line 401: `width` +- Line 402: `height` +- Line 403: `split` +- Line 415: `set_source` +- Line 437: `input` +- Line 438: `horizontal` +- Line 440: `vertical` +- Line 446: `update_status` +- Line 447: `world` +- Line 461: `command` +- Line 502: `path` +- Line 505: `executable_directory` +- Line 513: `path` +- Line 521: `path` +- Line 523: `directory` +- Line 537: `export_bundle` +- Line 542: `image` +- Line 563: `paint_canvas` +- Line 564: `paint` +- Line 565: `dc` +- Line 566: `bounds` +- Line 569: `image` +- Line 575: `info` +- Line 590: `acceptance` +- Line 613: `authored` +- Line 614: `location` +- Line 622: `saved` +- Line 623: `before` +- Line 625: `refused` +- Line 641: `snapshot` +- Line 642: `player` +- Line 646: `hash` +- Line 647: `replay` +- Line 649: `initial` +- Line 663: `snapshot` +- Line 664: `player` +- Line 686: `finish_acceptance` +- Line 699: `overwrite_refused` +- Line 730: `phase_` +- Line 733: `window_` +- Line 734: `canvas_` +- Line 735: `source_` +- Line 736: `heading_` +- Line 737: `source_label_` +- Line 738: `instructions_` +- Line 739: `status_` +- Line 741: `keys_` +- Line 742: `setting_text_` +- Line 743: `unapplied_` +- Line 744: `unsaved_` +- Line 745: `load_error_` +- Line 746: `exit_code_` +- Line 747: `acceptance_play_pending_` +- Line 748: `acceptance_play_started_` +- Line 749: `acceptance_replay_hash_` +- Line 752: `last_frame_` +- Line 758: `wWinMain` +- Line 762: `count` +- Line 766: `phase` +- Line 771: `enabled` +- Line 791: `app` + ## `benchmarks/benchmark.cpp` - Line 20: `started` @@ -105,6 +280,33 @@ declaration locations. Regenerate after authored source changes. - Line 47: `action` - Line 49: `operator<=>` +## `include/forge2d/editor.hpp` + +- Line 19: `EditorSession` +- Line 25: `EditorSession` +- Line 26: `apply_scene` +- Line 27: `load_replay` +- Line 28: `reset` +- Line 29: `play` +- Line 30: `pause` +- Line 31: `step` +- Line 32: `advance` +- Line 34: `playing` +- Line 37: `reviewing_replay` +- Line 40: `replay_remaining` +- Line 41: `scene` +- Line 44: `world` +- Line 47: `recording` +- Line 50: `scene_text` +- Line 51: `replay_text` +- Line 52: `image` +- Line 55: `scene_` +- Line 56: `world_` +- Line 57: `recording_` +- Line 58: `replay_` +- Line 59: `replay_index_` +- Line 60: `playing_` + ## `include/forge2d/entity.hpp` - Line 20: `Entity` @@ -324,6 +526,19 @@ declaration locations. Regenerate after authored source changes. - Line 28: `forge2d_arena_allocate` - Line 31: `forge2d_arena_reset` +## `scripts/build-native.ps1` + +- Line 4: `ErrorActionPreference` +- Line 6: `Repo` +- Line 7: `Destination` +- Line 18: `Package` +- Line 25: `Metadata` +- Line 27: `Source` +- Line 29: `Dirty` +- Line 40: `Archive` +- Line 42: `Stream` +- Line 43: `Hasher` + ## `scripts/generate-code-index.mjs` - Line 11: `root` @@ -343,22 +558,29 @@ declaration locations. Regenerate after authored source changes. - Line 35: `lines` - Line 36: `knownTypes` - Line 39: `match` -- Line 44: `match` -- Line 48: `type` -- Line 51: `functionMatch` -- Line 53: `qualifiedConstructor` -- Line 55: `parts` -- Line 60: `simpleConstructor` -- Line 64: `splitDeclaration` -- Line 66: `variable` -- Line 73: `render` -- Line 74: `lines` -- Line 81: `path` -- Line 82: `items` -- Line 84: `repositoryPath` -- Line 86: `item` -- Line 93: `main` -- Line 94: `content` +- Line 43: `match` +- Line 47: `match` +- Line 52: `match` +- Line 56: `type` +- Line 59: `functionMatch` +- Line 61: `qualifiedConstructor` +- Line 63: `parts` +- Line 68: `simpleConstructor` +- Line 72: `splitDeclaration` +- Line 74: `variable` +- Line 81: `render` +- Line 82: `lines` +- Line 89: `path` +- Line 90: `items` +- Line 92: `repositoryPath` +- Line 94: `item` +- Line 101: `main` +- Line 102: `content` + +## `scripts/smoke-native.py` + +- Line 20: `run` +- Line 71: `main` ## `scripts/validate-repository.mjs` @@ -408,6 +630,27 @@ declaration locations. Regenerate after authored source changes. - Line 99: `left` - Line 100: `right` +## `src/editor.cpp` + +- Line 14: `EditorSession::EditorSession` +- Line 18: `EditorSession::apply_scene` +- Line 22: `next_scene` +- Line 26: `next_world` +- Line 37: `EditorSession::reset` +- Line 38: `next_world` +- Line 46: `EditorSession::load_replay` +- Line 50: `replay` +- Line 54: `next_world` +- Line 64: `EditorSession::play` +- Line 71: `EditorSession::pause` +- Line 75: `EditorSession::replay_remaining` +- Line 79: `EditorSession::step` +- Line 103: `EditorSession::advance` +- Line 108: `EditorSession::scene_text` +- Line 111: `EditorSession::replay_text` +- Line 115: `EditorSession::image` +- Line 116: `image` + ## `src/pathfinding.cpp` - Line 18: `max_dimension` @@ -514,9 +757,9 @@ declaration locations. Regenerate after authored source changes. - Line 85: `hash` - Line 95: `render_world` - Line 101: `left` -- Line 104: `right` -- Line 107: `top` -- Line 110: `bottom` +- Line 105: `right` +- Line 109: `top` +- Line 112: `bottom` ## `src/world.cpp` @@ -563,6 +806,46 @@ declaration locations. Regenerate after authored source changes. - Line 235: `world` - Line 242: `run_replay` +## `tests/test_editor.cpp` + +- Line 18: `scene_text` +- Line 22: `require` +- Line 26: `rejects` +- Line 35: `test_authored_input_and_replay` +- Line 36: `session` +- Line 47: `snapshot` +- Line 48: `player` +- Line 55: `expected` +- Line 56: `replay` +- Line 74: `test_apply_is_transactional` +- Line 75: `session` +- Line 77: `hash` +- Line 78: `canonical` +- Line 85: `invalid` +- Line 94: `updated` +- Line 105: `test_replay_limits` +- Line 106: `session` +- Line 107: `old_hash` +- Line 134: `test_entities_and_offset_rendering` +- Line 135: `session` +- Line 136: `scene` +- Line 137: `prototype` +- Line 140: `entity` +- Line 151: `origin_image` +- Line 167: `main` + +## `tests/test_editor_files.cpp` + +- Line 14: `require` +- Line 20: `refused` +- Line 21: `rejected` +- Line 31: `main` +- Line 43: `file` +- Line 48: `linked` +- Line 57: `oversized` +- Line 58: `std::string` +- Line 65: `unicode` + ## `tests/test_main.cpp` - Line 39: `require` diff --git a/docs/file-catalog.md b/docs/file-catalog.md index c369a08..8243a35 100644 --- a/docs/file-catalog.md +++ b/docs/file-catalog.md @@ -96,6 +96,26 @@ For declaration-level locations, see the generated [code index](code-index.md). | `docs/reports/validation.md` | Records compiler, SDL, repository, artifact, and pending hosted-CI validation. | | `docs/reports/generated/.gitkeep` | Preserves the otherwise-empty directory used for generated CI reports. | +## Native editor additions + +| File | Responsibility | +| --- | --- | +| `include/forge2d/editor.hpp` | Public bounded scene/edit/play/replay model contract. | +| `src/editor.cpp` | Uses actual engine parsers, world and renderer while preserving authored/runtime state separation. | +| `apps/forge2d_editor.cpp` | Real Win32 scene editor, focused-canvas input, fixed-tick play, help, recovery and exports. | +| `apps/editor_files.hpp` | OS-handle ownership and bounded/atomic local-file interfaces. | +| `apps/editor_files.cpp` | Descriptor-bound UTF-8 reads, flushed atomic saves and OS-local profile selection. | +| `apps/editor.rc` | Embedded Windows author and product version metadata. | +| `tests/test_editor.cpp` | Independent scene/edit/replay/boundary/filter/translation model oracles. | +| `tests/test_editor_files.cpp` | Actual Windows file, hardlink, UTF-8 and byte-budget cases. | +| `scripts/build-native.ps1` | Static-runtime build, real tests and fresh portable ZIP/source/hash metadata. | +| `scripts/smoke-native.py` | Extracted actual EXE, own-window/timer, export and two-process persistence acceptance. | +| `.github/workflows/native-app.yml` | Actual package CI with bounded proof artifacts and manual-only full-package retention. | +| `docs/native-editor.md` | Usage, fields, profile/recovery, build, boundaries and actual captures. | +| `docs/reports/native-editor-2026-11-10.md` | Actual observed validation and pending hosted/installer distinctions. | +| `docs/images/native-editor-play.png` | Actual custom-scene/replay native window. | +| `docs/images/native-editor-layers.png` | Actual collision-layer scene in the same editor. | + ## Reviewed documentation editions | File | Responsibility | diff --git a/docs/handbook.md b/docs/handbook.md index 46a63de..214be3c 100644 --- a/docs/handbook.md +++ b/docs/handbook.md @@ -2,6 +2,11 @@ By Jason Stys. +Current native work: [Forge2D Editor usage](native-editor.md) and +[actual native validation](reports/native-editor-2026-11-10.md) describe the new 1.1.0 Windows +scene/edit/play/replay workflow. The Word edition below retains its explicitly cited historical +baseline until the separately reviewed updated guide is produced. + The implementation adds bidirectional collision category and mask filters, versioned scene migration, deterministic state hashes and initial/final overlap CSV inspection. Supports practical game-world collision layers and reproducible debugging against independent geometry oracles. diff --git a/docs/images/native-editor-layers.png b/docs/images/native-editor-layers.png new file mode 100644 index 0000000000000000000000000000000000000000..dd6c62d435e82a276ce13ea190b21d5c51990acb GIT binary patch literal 98006 zcmd421yEaEzc1VtcXumLw75G3f)p*#;u54tu~OVZaVSnHE^YBrAh=7gKyjx8*Wm7w zo4)rv@AI7RoH;Xh=DRa@CM$cdy_fIx*WZ6dz0y?1!=}c5^ym@ZOBI05qerN-j~=1u zV4@?R)JwRjBQKBLbd=>El@HTyBQvPBavE}v9#zKU+*zO@^H}dy4BZ|*!teT%9z$J< ztsgx?6ubn;z4kWSYsE15vfWxPdz+QLSM4@@eHbwOa-m;cK(PO8lhjs;4!S7$G_qA6 zOtD8s=Jyy?jw_N$hqRg9Gh>$K6PhB#Iq9W9|KR$ydArLoPy2Zl=Tn0mwi&t^SX-?D z7gc*^eaqQVW_t*sJSJo4|NhevF&lsW?;P^^fdWM7@4SlmS0M9$6h*$wr+oz``bTAa z_SwJ7Vsc=RI{sZYG#Le3j&$Z;n6Af<`^?-qQj<^#?sXb1b`b}kn1e?J4Y=y^p_>aa?A7+0g-WAFsgOlO^|IlW<^KC=McWI|M~{zNl7JC{<>9u zEF(8ZUV3({LC)(yBN!0jlSl7%)#>#Lb=4TcR|EtFQI{Frfl zHtW3LV<%PrgO`A5a#gf&`FtkO#UJki*X8(L*23#X&i_FX&;PE!s9-Lv+DHHB0fT}1 z4xD`?zyfwL{u7Zhjl?OW?7~i?9_LZ7+x>~{rBD*A^C9l zoLHkmv|7wPou5OoB9OYT*`Lllz;uMr-e!a`zCaT>X_}zk_D>c&{y;_}-s}j^0r_PT>FUWnVMcc0romwD+beq^yUE!r^a1r!@l%R#@B`-3 z1mdV?!76~X!G@FL{g2eb?ebl{8l#0}sf>f`5-0Oay6X}GB+qR$vML{D?@RXx2Ak|s=NEWe$5ct)l99tRp zdFJWby7-20>F&c!MPTgXkSEzZ{9k4cRKOen)@hef@axtL?RuvfdWVI1wCJCQMMY_7 znS<;O^EK(m9sw8E6w`;zgUP!K_3g*fS5->fRsprumn-t1$7Y}nGW9H}A-mgi7f?tt zx1_4{<;HIPk#=o7p7=X6p67zZf!C$xRMltJ*Tw!W>#h3x#$JWrE@nL5ud17s%oNCC z{6*X+LZ?!gB6364G$J2rp?^Wt#cTE0kR?;leS}+-U2$Ktaat>&SsB$ zF%;)t7RpFvM-3Y%M5${DSU7L(KX5@918!YvlVZAN0&U5?gxSrLHfPyL)Xs z_cwpBK{H(Iij$1mcg^`rALR;q^;kxtfh2(9`-dS>ydU!ASbzFTdUd!_z1;jk;?9aK zPwme8?x^eX>f!eAC_eCxZV7bD{ctnWzC056P;DHnkqarb;Ymju`%$|a+t&0bN%XbI znqWLZj`R#?s5NWSAW(XQ&zxiTMbPh1rCx^kbK53vFtdU|qcMBHJfUpt|w&cGK zT!=%>l+lFGHkKX>_gne!_-Ni=4<;*v7uee(2xNcQFwb@}=f%zd4~iJjSKvpFs*$85 z>HCIjN7ONNCpR!E5YexNYsgxmk2?El%ApK{Q_PRSI%W{}^@&cx$j9n-6Q&t!U1jmt z3cqfMwbRepb0vv#8rZ_uKK_S4S%(6pk0Dse%yJK6REvK>-C-Zs|8xbXau_R{*P* z-y4U=PH|3zrK5v2Y#jQNRIYvBWOLiMRF0(xZ^;(HLz0oB7lJ0o&5dDnA zkkv_GLcL8?7I8fiyM&FL#U7T3*CK`C4aZ@#R6EbCpIHK!A}0G2Rl)tBw@kB>9&f{wXq}&` zsVWx3M@n%-48u8#UVU<}s^3ayhOk1He^u$S1X*hd8crAEh@@lLa78Tmbrh#=lvc$| zwFv2$#rryY0g`xT0qnm@N;Vbf+##%ou(%rcHCO91)hn+ZORn_R4|#pwf%^gb2Vnmm z&QL`FRs8Oh3(&-vzVuSTI{kXCsy=5>!0ke&;rZ)HUQY~4ly6=;}{Y*D^N&ZqAw2)j@q;V<02rV%#MfH}a!)u*SuDQWJ061U^;Bp00I#YIv;#P zkrI6Igx2Lfx(`p|H$u4XtqaqLeXFvxd;3qOLi2~Fx2oBa+>uN3)>LIXSmPIx+1{D2 zRbm!neJ)&`*vX|C=MeYsE7^J<#?_xZ!@ERqexLd_MSw(o=dFUgc<~GC^uajY!)*W7 z6Y0N~32h0Vu53v;vG(M=pAlo{dfkm#M=MIjuR;wWf%PAZGNFhnU7Z=m*$-e&FDYc! zlxM{hb{MOgoGl8{wt`AZalg*y;S4ydV^eHIgH2LZ;~DCaXJOT`$z7TS#84^wN;Ae0 zLZ(~ZKHm+Z{EOf8oxWJvzojG<>$b5>i0iAJ*WFT$Eqh0QcWvx`usBg}qN`#&L*M#G ztNO(~yBGsIFBh1)$(Zaig&YpvQ}O-9`sE{!OmO~DM?OdB|3s<$7##a=1tT=!!;AkDUDnKZ zyC8KPLEFiP+x7R4*Vo;)Q2R%4aI6Jo_}@SEv1}?dntznT?eZpENY@7Q|Fd!o#(!Vz z%~zmgT;Ik1*kX4Bx8jxUn4bC(T|9UFLsXzD!|vLrVOOrp(~yeuYbayw(JkAN6xkP& z$O9oF<8lPbl4L;QxC?O|X~WLtGdE&>Qlo%*ZcP2ntny1w7}Ch{V>eJaWpkhMOk z>K;D~5nTdR)KiMr{=jGg&_Z&Z=Cmx{#B->$-s#`1Vdx6~V-o6U052Od_Sw2`hwUvv z<Pc*dyRzkj zC~JBhjRL|&dQkdC`EIB!^|^wk#ha0m*(?MFoB8v9%!yat-Bu40ysyU903SS(vWMuA zobvj|Gdy73U9b8JJ%sU2FI>@U6%mxEKyBXn=1N~nzAAQfS@Z+`XHVm`Mno;@r3 z`3H7loJ3e%JKrYe)UK+}6{WBsDd85fW$}%_J=msTPI>7gh1B!rcYQvLzV@6T=-jz(6U(kA7&IZVUz zmiiqeg4hvQvmb=WNK{iY;}-l;mJE3!Nwgo}%laq2sT<1-;pd6`Bt%3q^dQhc!fE{B zvBI&Z`o-a^5Bu-cvQ1v>NE+=xoj(DV7-p(?XFquXKh>I}-aNqc^&p;1O(b_y4wwU- z^-FZnPs8WOo9z#{3?e7N_1c#xn&t4AI6C^vTjR#T%*^02Z?-~@ZA{saimg|$X1+Y*t)!XX^lI^USb?{i)Mtk8eq==zA7~scw%^k- zh}fZ2utXdy4?Ow@>6vxFhkpj6!L*LGbs2W)9f_cTEJwkY!qtChYO{^9FeMrNT(N?? zUUl8T(DM20r}}dUjSE57Vnh`|W?x-y-gf?!0Yz>|rYvpONeYOvZL}&&2;?Yxrpevy zCF=MHQ0h zF*yf_ID-Olwaf1LTdYfdY|M!s#WTb)H)(jdQ?`=3?ygmOT41zX=TWEWs)Dm$xWke_ zyQ(+$4d|Q6n04Q+qGr>cR#?zxv`pb}=;I_*yE0|m!(ea$HgZ?P6OTKRo=uR;rTobk zm;K=#nSq!$oDDnDdN+3+&-zigO}oZkIUYO|L5OMc*+(tW$nw&vJ8+b zrR>U!@m#g;G|alC)d@{VGDXoPOl*ISiW?LLTPs+kHne{C-Oj^dKn?Qubyq{jf z%7%1wtEW#A62;KU9xnahw6r0@RA}Md)_*h2&7PQpK~4kk?*mARTWS7c4)FOWrD}u? z(FYkOhc;h2S-LicrPSZxDB!L558>mWcr8Dn(#>f8=Haz?MDlJF(2u6;LZ(KgaFxvN zn0b5G>CDOe*5l66K;q%yUIh2*7zS_J;i5O1PPdesFt-5QELmJ7lV~3uF55;HEFtQ7 z`7eLcN<9tUr^AH>jEonFp_e`EQxs3n!kF^jA?Rgk>M)iTBb9b9o0&H<-saZGnj1yh zAo9pJcaQ{7Fvfemvj!R}$Tec}Wunf$Q#0#o2SpKD85U==d}q`D>ITIp$6~$LOtHN# z#;m&>^SF5Tlgvl&$?v(1Xn$y*;i{zbq>M% zDDI{pTCax(l!t2#nUtCbI;8_pX!{OHr{++&S1###;3+|~nm_k|g4fEld0Ut4FuXe)GMqXw8WxCH^v)@8GV3YMzC2Ft6t+VIW-y-ZF>tRQWcr8J1q_W} zWFr;7w>(5||Nbz�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
    XKkk{B`}dFdUOa@hW<7GLm09f* zLK|~=@PE%9erMmNYSQUb0CpH&IkS|!MD+aW<#Y2CM@2M^Z#&_#nUAg-ug&2N@tAk6U_2FrA}j1kk)Fe{AX1o{ za56xxT)k9We6w#))*$d#fvX zA5>=P;M`6CX>4k+!9f)#xdR09tBYxN&FOP!sLL>A!img>{e|Dd<^3%MsC2wbqnI`I zZ8)E%7}TmNg|nbPaEQvDfhBt-ow12W*UH7_+iX9Xlh=dX=EAItvz9$y0Y5drI}4{B zJQovD;7fFs_NI(0r+lWhSBy-afCVctI}TE&O)~YcX@kc)B-T_%8J1zwXKOQqsp;+P z&nnX3z@jiP-;cI_5+>dp`bX!wKF(r#a|wtpfx^!@J#mE9hZGMKn>EkJ)B7cAvbgp( z4Fnf4&~2Rii3#ksuKzhT4a-7hfy1oLl4~5HfJEJ(bTW5KXz88A#75ijh1JDvqExB{ z_gceal&AZ>{1a3D)2+I-dT_#p1XNJ8^J!B|cyyt`VZKBY)~+{7+G;?}g!Ph4`5Yq@ z`(tTNwqH#vF)hWsTIu|1t(e(QxT>*qpXtWP35HSFS^F@E?jRO6Ir!Zdz)RC_tjp;s z5scWRzuE8GD*NHHfYv!y zOd^jv%Ct*oCGFo!2G>M))SwX>fdCD#sf8AGKCPOE9l}EGv9Q3&`fMrALn_^yTV%dI z$6`Z8+1S{}!r3`u_R5-$nJXK%D(q@o2d58}{KhVhDp!a25bx|JRmd-=mGNwPwjEqp&oTy6Llv zSoX6duLBj5TdsT7Qx71h3(uMBj!S(%1*&{$Evs%2W;SkAjB`+vdq}W0L5YETF>7Bz zwLHwA&4V2dRw<81DORse7gU{0+sWxhMqb56l(zVf)k;BgL)c zukK?NXjoXd+c^pVd857(w3vd%2egaMzc(n*?4T`NyzF>jR#GA|=+A3DuA!4}QL#cb z3K8wvl9y7Ce^Rym*YVbw)@(xP?$yp2E$rZImNbBG_K1ITbiS0_{H86L(qv?KrYjH| zbVQk`(DgM+chjjWoOSP6{!=2`jYZjw#jO*XhQqXmp!w8?m5*1juFCFejVeJde}ker z>t|DFHuPcp3@CH&v{#fsM^S-@O9@!#QNhMV(O@_I4705 z!}X;Ru|~`Wd*@fN`Ya@)Sc(yBTYznHRWX)U`!;+jl{#f^aEf4_jLU z?yV}t@E=2Vl|G^$#%9HigRH6BYNVBo-aS!1xs_(9n%F0?VVgZKHW&UgtaJual}v5=%tzv%d|_2sQO4A0j;E~}#0ox8NXm-pSZ^k={>d*V(edpk%!d=Kt6pH`jm2vp5&yrF5p44qA#I?wBM! zh%Q}UDZm6-*pxkSr_3R=K1= zk*%mTz?b+Fp)05K)_9XZOGbIsL-(mxno9eZFGng-8&so$&8_<3$FqLb9>c3PkL825 zp2TwCGykWsoxQmdzm@iRUrBxO8g0>^xwKZ$b89O)rtv;p{d~#ny!6(bpYO8*GpX;# zuV}-es_(Z0ha)%tYQ3RovyLgIw^4#5F!uF}T%RemV_B0bJ1p*GF-U0n>Cpzk{uW#V zwhS<7jYr^2r(c=ai=|9t7Ft|*k)2+kY7^H6({ply%Ho76xOp-}t1rLP1_kwNs)SgV z#1V;h0cK91yTXH42#i4Q%%kxng!CU+lR8XUWU@+<6Rn<3E|Pv?HXOyf&34-1Tq0?#1tE2DD> zVAiJUMjhGA1DyGIOGVklE7#1h{--7{rviT7>38h%$wy;==GXwM5DC_0k3^tnyugEf zFqi^vD%c`wxmJ6tP_FmjwCRnJ$wSikAPNp0O<0EIDE{pG>~55RfZuSw3S@J5T;t~T zbQ}6nB&}V&w{lk}9wTQ16-k|Gv;M+yk)J}{104Dp%HYCz>B+f-hXPd^eSx$>S1E0; zO{V1UN)rOs{1jms?X?>&)S4rwXQp{zTkBJn3=>Q}}{IsK})auG6><86GSm2a11 z{1LDu=-i)!rJkMzMmI01;8=`zYIr7H)ROAEKX1rgbQWXTY)V_#r_Df`8f6xxamIl5 zH3A9~4`pt=Mm|7Jwhumeuf;um@&+k(*9mM4bU`E%8h1PXJtvmbLmZnQ{67mp&zRr>^AvB3|{*7O1_LhWVaRv*WR;jJ!_z>y1skq1Wx;e zR=d5~X4qcbAA}Av>A$hRh*K~Nax#TEmV^ z&fMPJL&I(j-e}BKL`mcjE(J$m_y&-7{i8qB2O)5+n3X|WnQEn~sm!Ww)@&}mln`s9 zx){P6l7R=a1=%CHYFC1-0;T7&O5hs0kae|yX{*!Ou7uuXv0nV#9jEfG%1qm?&;k~i zhfBRVKg9U4tg=pf>8ElW6&&A~OwDFOaGUgozytP|nm!E$GE$x57H4`3Jvj&=H{Tgp zvU{IyBm z(t>+4sjF4jXwBeANxzRHkoL-7qu(vsr$C|67>32ty%t@>>yYZV6B&+mFdet9P~tNW zv^{EoNWbi^lb-w8xnUrmn4lmweMJ`7YP_r-(deb!r6O zmW<>zI-KR>uSX`XXHh$t`ahfbjN*C|9agZGv?J2liAlC<_rANsI!iiRlE&*j)4S?g zS`6))U_w_C$_L_Qe7(Trho{f1Dd03p{5D#8pvb6XqQUEE&Zp7WQLPVtdb(Yo1_b^@ z(FGi(uRJ3YqPhH_PmL(pV2o&UPy4W7%=NRnxQV_@MvJWPV%S1tA&xtm!oMs~SL9Zi zF-qaX^kbhkt1rHmWFfIx0>(`3gKR-dt-J6eoB+3pj%Sd16QK~c>jfO1D(afLkHaRN)cJPi9Aj&ILYMMB zm529pH%v^$|DgB%8rmkbrtM8Drxn`pKLg#(YS6)_a;eD(iL|}L$PZYv$nGT&wP(8K zcEE=>%eHA%xX7pMqKPkwpWi^tc8K8ajnt~=7Yoo=l7)LY1yPf#sC|DYIPSSTJvZtV zyBa6*Kou|DB}d*k?sn5jw-s;5(z?w)R7o>@qGJNw%*v~Fd&+@z6V!>%8H31gi^QGK8$50j^4W{m6^ zjhcL#FYO{eoNm^Z1MXyTV$MUG42ptWfBmXOh|YndrPL)Am!z15Z25=fyB}`I#F?q$ zQflAUrcw*R*S5VAi?;QDr4ODp?X+q~#ZyX;-{ywaq(`f5c>EEyL7e24h&(FwpE`TH z?%A{=eq2DX0qp;5g|N@H#JGz}GDOEoILdybFQypNtuCIlZ~3@y*5d=>AI^+s7wsn^ z-72k(UVLta=iy0@rKEhU8sF=5V_z_x$M#DkJ+=TIy1KS zt9H-$S+(nm8+pM}D8AnQ>K|snoHLtL z0_b@H2rvmsD~+i+Gx5Y`-qTB>AQm^O-ajE@naCJHcj$H&hhoKi(ko38`|Vl#?6=cG(rqZfLSuGHIp$K~&Zl!E|g?LC$t(;xT+r#0x!%+6ZW71}iJnQLOFn!M5rf|9f*&PV0Xn zycoi{?ipEsK7ML#@A{+y&SzY-Z?&F6)x5A8vl0aPzc!#MNe`FzCA4^8biT7_do0wh z_#Zgc)3a+{m1NQDvw<&HI4}8+G3&~|Ynpx@bkQKmE*4}JMVkvu)z=PIv>Uy0jMP)5 z62mp?3!C?gU#wQ%p}7E^Dl3CZzPi<=kK8m%e5V&uIRM%ffTlzw<44r!g#c8(%B1LY zsP}=B?1sVPoqj6K7t;Wpw*mV0V)a0}P8bN;viJa4mw8g- zr*BUoA?|nZgvORR-+cX=bMpIjo;IY;s@%z$g$UZJt>y#hYsU>KnKU7ar3+YM>tNDMZwX<|5WmsX-|Ea?NsUqdbvFN#Q*c=-w zRqOCrIsg1Kl^ZI{Ou?mHRMdbtPS2OjwM{!U{;yhS%-?O!GX{=X%<0p=M_Qb2UwKa_ z_;1~*JlKUx;IE9r9Vq1?VwiAhP8+WQ5YhV}6 z+1cZM1gP0PJ8ExjZq}0dtqbl6u7cy&Z1tPVRw@TNx)0>~MI57?VXGD4)vW(Rr>;H) zeffljey_GotKLEmP|HG|83rdi*AveT_$*{PUI1o($CicZW4!jayJ}sP+X!I>Dd4W9 zP3d{Z#8tINh07gZwFR%WITM`1K;{3h5>(1|Yp!lIF02W}mC;xNo36m?2aFw_ywA5f zk}+#kf=wg4&1gfEV3CXTeX}B=c-Q%ADKW&LZLK>lQSoTXrEw#UgoRYnsZR4^t_h;MXHoo-r zP2Z#zaRiATEEmEjuuU53XHLsE6ei3?{}gD?10US56X26;%V%3Bc-60w&tWBcz5({6 z)5i?k)0j5g)~m73Q)OCqX?6Ep@8n)Y!8Tq?WK5~!^lpFx`@YawobXsr^wr&fR%ek- zUo>7-9{G~TE?c2(YgxVfz0^A~hV4wZhmrrHGON%@0yat}@-f@p&1UVskcz6RfcJbm zd(ul3@zO&U5#j@w2bEo}{N<^|by|ohn63~=x6)exzpguE2+zG;@dk z)|x(J)zbX7n@8M9_AmEYE{@S`(=0tG3fpS0)6y-@;NuIr0Ks>7jALHH)h^kIsyG-2 z^3(e6BNcqw&*I_>X$Q=Eb?9My7t{}i4OFHb{x~u&_pLi>HBg7{NRl-;UoTbQKZfNX zGwcSZ9sk(xTn1TzS(W^BM_%K^LIZrQDg~#$PtHgkzP?Yg`0rOfD?JGzcJe15KbsH; z^;qc3=~v9QuyLVQCl(QwFyB>K8F?Bq{*H{3Bbr4i=h&IM=f*gw=##4NHHg_^gkjKl z(&{1m@O&}brPAJ;ju!~8t99_X$k?@GDchB=v4pGwMxlHHR4|INpO+!y#}!m2>@%>M~EHjJ;CU7V$rRR`{~@q0fh^=<}*Ipp|DK2ZL$LZN+Ac=3nYb#AWk{ID9lgC5Kn^P|y;@Rtb zZeGBjpwvF4Bk$8$+VE(>zrUt~y}CyEr5dpC+G*@t{qac(!&@>jYfqUs=Y!)fOIi>$ zVxdJ2?+i)2yXjw~kDs;)^^9*J9qX#8O``$WPd#6T0*{DEV@!Dp5wGG$qpie~=B(8H zEABe&=dHi+R0H0i1z3bPJ#yB`W3wD69&huh|0-Lnf|~#_{~%5?Cndqo_5Z**R1-@f z!uMS%4z&Hv7B<$|*_*GN?$2etni721UZC5RplO`0C@U*~27AYEq)*2r>ApX0r&BkJ z5}GIAJO0+>#gB9;USTUEn&&mYjZ@cxwMgwDWu*GyMn!)B>YWlH*cBQW#Mzxaf@G_9 ztrlRjH!I%7>;Hlcg)F(GALrdI`=c5tA@7Z+_GW=zmz@yA;`scW1~O{ynRxeODhX%| zh!8%pr@X1>kU+mP=GK75s}hhM0p9DI37YXiHyfTt z3apNhyU)wDH%*dfD&`AM_$3kNacO6(TBPLNH14h*pUUS!*OM&?EwS{VMY)XxV^pI8 zy;hJ}LKR=q*rJI-MQgBgUINzwxOfzF7Vv|@U#Y#oQC+)7nKQc@N2wkb-(RQc@J-Mg znEU9yp}gOTHhoig$!=2Z^(5Amg|n>*C9cTdTddLZVe`mikzo8Bj}%bsb;5&w_mY{sUBaD{S8(DmCAA zS?-AzEV*A(|IrVuVzi;_x%Sg#k@I)H-l#zFs&ih;*LCH7aNqh8%5we3(J?v~+oQ7} z{j<+?&+_A*#9A(TVzK`1&#}zF3?q~0(hLrT`uM9CXz^)A7Qr%U$cZQ{G)YksiUAJh zwiRql{wow;-ML!6HCJoTkXmq&>l^qr%uZR<)i{T5+R)e~7Rt1@(Z>i{202uS0_I%@I)HAoS>A!FFJUvp%Z;I(p6fVkLYVT7@3Vnem zjn%r&08v+E!MnNMKFkvvZlG0aC~Xjf*q|PR)q27Zku_^=|GjzML4k4LTxr-PV&8qp zM&kIyc{8bAi?v;a&784bS+R_@Le1q%{KDF7q}oqsJ-U;YKWLK2VsgSg$ZF>rpBr+< z#DlC>Z2rX|m|-=YfX%5mi+Q_s$_S>NEtnk*WI;N|T9O)su;0VPlN7-YbbgZWt>%N^ zY2_0`ARs#TqE-XM$hg%1W z%+0~8(5~x=-ll5bI*H9qQj9k59wvNQ-;FwBg|D$Cv24o_&s% zc{_hc0!6HrWI_%B14U7FD@%!YwJw(_5xq?jhR5`ocf5_~Ycttw*y&1-Wz?-U+-Z0x z+;)Tb$+jr0TpJjKw5ZXDF3zZ#m~Pt;5t<7`PfZj^ghO9Y!rW1+s~Ryh3-hI= zNhAPn-j>iv37Y;bSInP^0}n|BsrPdhor2cn{g_IF+hiNP21nhZKF&hDot^OsJ@Vo< z(?a5+@0C}5nCi-Z&kwHafYvw@A@;+IfTqgY+IFu+&8T@-58tAYlZ=A9R#~|>LBMF* zdGU3JoEYcEfgc$bb@gILVJPKLs!G+G?qhB7QHS>*-W#Dw5_u;zjLR%i7%II--B!ML z)RXT$;LcrxxnC9yM0YzbQC` zTvln8Ywu>S{Cv(QrB{rYx2}uF3k<}mz!r!ouKlE#XDB`5uqdIjH0RKP{S190BTGpL zy}Zl0FvWb~MzvT4+)+R;2&apz>bMaOMP~>bpZxZO=DRR~e7-yy$BtwpkFW+&({}Yi zCS9o#y5dswQQ%jxJwet^tk{|IuK9_xjTtcyf~^V`)+|ltNX9*DstaGpU-?D~^5w(~ zC1>~yoSD@C-rG0HbtU97%{oRT1gY76v-2N$gJqGLN};bYJzo%t-qa13$wqT5*^;s1 z=QsxESl$@yC`Qrh*UY&Si;6Zju>8qs#mMmLwTL$&-1cNsF^qrf`2MQWx9gg^uFy{z zwn^MEosVJZ8J?iBsw15^B|mOndB%Yjv&g*ynOK*>!|Qpr)|P@g=bcyLeY{5lhqA62 zr>$}V*-Q6kDtBK@*Th;ix8LOmXP%icv}iP^@42ig;w0J&F&c*RvfySESFNaCH?5*iG zE*vR5+|zI9Q;l#FT&4SOwSruj5ZCf#;}Dl%ND3U>+@3%`E+S0l(g^*>@8;>vzE&pp z=kyhvknjXIcoHRO@;JTc8zC`pq063R1-|}a()y!sN1d}RTv62lWI{oh*Kfa&k|sK@ zqX-eb@{wfND~G3i)0!{)$$I_0>8#aj6AY1vXRKQWX1_Qaa&?7I=Vu0>HWymsNnQIC zkl1{L!7r->TchI}5ccDv^U^n&jc>igS(AW)pYnb4;Od`5+8|4rCsRB=h@1QPfjW9E z+0IO^VPt(=`Wk}A+J9&Le%i`y<1MwWw)$uRYjVY@W-A)G>D)r?jN}fdUatTa;0p*s zy5O8vK>B-cW-Rdc7@;ba`+_w zmu6Qp#OG<_&JRQX3D40mh(PS-;vaAFt6fcFK9ig$Vz;MHE#{em1W#E#3D6hR#&4_c z=xo-rCvsk2d^+~qFb|d|`7=J+2G+9mlevxXZx@{>q=kmhN(l4pzT(vN)sS}_G*)*QE}cBeiQWFsR(IKx<58}Oyb&4zlf{( zdsv3h55|=3x7o~_(z+MBYYvp1MsycX2yBR*d(){3eu6V9{%SNN{kGJ0y}dQym%QVZ zb|s(CCZ5kcQvFV{KZTfqza?zZKZ{2IM`D0MwUGnPDSHqI8y|_HF(Ue7mLlD|y4(6E zQhLuyi2d`L>$ubWm$-f=Hq9~_ixRgrONRAkj)S}-;n%uP1{Q0U?R0aIGC|`Zk0S#) zcZN1c!b{yGd_PNDJB`1(k0Cg>U2N(5r$3W6OzFKVbM42GWXN*xu>^wqHjOoxdJ|;u zm+}K5_|yaP!80muTwJ5O*wHMjuSeC6Ol%=T9W-WMpWg?4@GQsW`-d)6DkmYE0Xx+7 z>$ktD2SxWgy=HBKJum1S?%NKrVjmicw*RSdzxe5UP^BskE1#{0ntpP%xkHg9oy+fE z2*2KR*M)pkeDA>9rTSEhpOU#DVk_NVpZPw!wm*Nb*l~BEl!V!IZ}~w&nOo~?IWyLG znT`hAX&npwb10q~y>$St*AB=6VnFVTKxLGZXQA6XM2 zPNBUp0);H7$1g=po=^y?ymfH#?(A)nJ7k@H4Sf0ndFcjw8G7w$V-7y3cS+|BJUv$% z*1^3hfuaN-%*eocu9et`VzUHIH$(cASdSdW-NX!o)wMZ^y3{AD_{GmWHoox>=mp8O z>k>>Bhnj(!E+xc5w55{I^F+>F1j)i%&#Iu|R{592odZZnrU)Fx9 z^cjBb!ZW3WC-7MA+&Ug~mjEZ$rrSx2efgo25>q&-)ZBHn<6o4~Ypq9?bX>6t_qrtt z3Y75IJ!gUo?d~$aWe=#@cQhhrj~@X@_V~Sf0^e;>qYstn0$ZuS8- zjP#6u6A{;^T0N|U{VlZB)|?aTk_9JugG|GkYazGnil*uqTlW<^17fIC00!cSnkN;` z@rAq`$+)FOTkJ&yqU9$Vu_w`}f!<(os^gSc>0ca*Nlr_#YFrh9RhJu+%xu~hO}IW- zBw*dB-KIQdSQk?9yg6oN3lf6uz599ni+|R{U7L#y&5P;B44V+GOKk#MwJ8V#^B^Pr z2QY^%1-w$qU!pA&H&KxL%IkUieghDxn23{i$`D;H8gBXoN18j|nd2oRom3L->Suo^ zwo!<4H;;TygR(uA_y@suY2_pgCBCI09)riRCc^>%J^VoY^$QW$&s7+`6o(YkLd@!} z-fKtISIPuXdlIuV=@Yi0EF2$ir~fN(5(Ay25v*$Q)i-)N!P0sE)SHn$$Y|!kV=vIK zM7?s4mQ~1cQZmGUZ%sBtbP$Bz%8wE2rutwqH}Hu7cMZg*z&y}j+^Kh2)mns|>%$X| zn1Y#nbNVp0BL@e;1Y(9xl(E&N6mYGLkL*{0ZSod+rOY5Fr}F=4?>ztEY`cH`q!FSd zM2H#@MD#W~5kd4QL8ABGyU~IuiIV7@L>avsy+!Z68#UT6Mw=OoVPARf`}f&<{{{Qa z_WHs#^*qnDj_vw^zhU1rC;Ok@tytjl^0E3I17atk`FW zoUkRnxS-YsGCBzE9g4__c0Z6!hD1gQ+)Vf8DGi>zoxq7y|2G}8W6@Jw2lEa?KmAq9Or;t>KWwVJiB)nloyi`H38NG^h0H`hwb%D1&IBtyaq2sOGg&kq=) zBG^%LhRw-A1MW&(tNw*_`%UESden-2+04dDmivK*VS%3EO{DYV9%=zn1~M>ReC8d# zLY=uYDOIuP$q`K6`2e z2<2{9s30Xfwho)jhOJ^Y*D!k0e^7KAB>1+5u_!+l!kv(xQ|?#G7YbG1diI4ru5@SZ zaaH`DrAuwJ3PNd)37S2|t`2`KTw6T5J0(PzBs})8(#Y zuBy_@Ts?~R_iMT&icY-6;jP($juc~~%Z0mzIUVfO2wGW}-Zx&Sxec`v4Dd5Sd~N-~ zR>c`29iFDc>JEwk)4)=cQkg^~~Vj(~=5tv5pd2 zV2aTD`N+Ng3Pr? z9J9!ZXD{0`AHf3beFhC}0f&PO9a8VEy`YQzr89Hi=_1u^G+3fSy38|8_>f0}bL&sW zw-@IPV&O7`HuUuA=QaLj9R(aP@u-Cp!Qqd!ndCx;Jj=9$X?utI_TD*op-esW!ypj_ zACw5RY*AU?hlXhkD7`hIH(qPwih|0xQ!@kgRg68!Llk9m4r?b2QLDxbY|Yv=JJU}r zm)@#RNDTA)f7hn(n-xrtYIycSW($H264wKRaYnHDc(v;c zJ}v&M>*rXh>NVZB1g%|aPuavqss-DC;^5_!3oop9A6{E}~vA!-W;2sL|q4r+We?a-vtmOT}4<%fso z3mUZ3E&{?S!f}2EMvb$w@WV0SLI}-JD8Y4P3|M-o)x@Aad1AbC9(;2>N z?Z8k2n`=1Db29}8aqI1fxu7iXZ`YK0V5sR`$7Om~_Uunjw6iJJ%zNSA)1zJmjz`Cq zD9P>k@kFE49im=+4qpr;Sfcfd_!`5=HF)O~rejm_Amh0)JCpY|32kd`L`)>p;6T(3 zA1ql9fG;%B*%Mr!iRT?g;ru;O;zetJN@s+9WyvVWI~-48`Zk)u60j-h=zNibqjI4SRNbWkkC6m+3O{6Q<=QMG!ZYhsJe}E+1>}^&w zBUeW(;(?c2QB_J#BLF)@|FKu5ofu8J!YMm_z1Hdgttdg4UU|a%zM;D(w+K~2>V;d! z??aeOGNMVk7i@)+C;dJi>A9it!pSLU`XDPjWL*uEJJS!&> z2c&eo*qsEM> zFQ9lIcM+NlQgX6KvS$-LEka|Nv~{q%^7w!0iP}v>>pPD~vXN|?>_{S>wslEcO8 zK3tX2_VC4tsD?Q4Vs5Nyy-;K^Js=CX(dw98d7G5{RF&i~wAjqfS@%%+Oh!w+$EdQxB1R&?m|P9;2(3d?~*XKAdzMlQSq<4W=a>v*NlAAo)0|5Xjuf5Q>S=A z2TH$MN)jSavkeWIFF4@BV4()*wwC=5TOR|-nxlm_pC-I9n0YGL@5^ayXY*`mj?5}t zCUm!Vr2%=nUX(b16hbsZ)Xx2E*_@jTfApa*C}!86#>Xm)Rp;xQN+DRVl`&r(1{t?+ zRVKNky!&w@__nkD-kU2QC+!Lx{VhEiiG}O^1$aw#yopuhgZb{#9{N1h`}5S1{PkTH zfe#t2Lgw2S65W_7^1PQeHr9GmA0osvv>PAl=t_T$r7I`F7b&Zi2Uqz7K4%tEHR1ix zp{=8&+OdywT2X(+jxAKF$Y~8c4;Nd|{wE2U9l;=OtmzI3-6-H-=jH9}{`2f-lmA?A zv*vv_AS#ez?8=kMWzlHu^~%wa&D|qk`Ra1x9<0cOyHCWqEPltJh*mV=4aAqs?A3bs zaIG0#1G*Zq<$>~vH{4$&VNhJps%|+WUiE^=I?pdFW0&vX^GJ9{#|$8J#Jm?%zhc)P zAMOR0WC?h2kQ(G}?v=Dz+O9S)+VXde6|oZk1xrx;_`N-Z;h$2ty%skc(vz=oG9OsXwsYX$@coN6o4;b z+e|;${1XjAy^!C^G6QMrzQi0Xh4*w03DoC1D>njDxPM(9aJ0ncj~6>>qFuzGx7Z(8 zw6VUkoym%rPpA8qTvq4V@<4@1FvE1g)Gekd&A15N`Z~AG79x}`%&k{SyacW}K34oG z%kT+pxw&8F56h$rug~;6Xr-ins`bj<*DmsOC6CU`i6?S!Ako%BozrD$OoNYy?>H8@ zLVJ~POvG;N?l3aKc7C2WUaG%e#=K(154v=L5RTirMW}J-A|~>R1!eq2&YhNm@-J7j z6@pK8>3n~md(-WB`nUizdXEz4u{)@9QN!oZ#}+l@i*;2vf<=@~wy{bttt5Zz75c(b zr$*O!OK-v2Cu2EF+M(gpmE^CHU44hP;FVlwV~6qmr9s|bV^KL@Z0yp%3J z!HufGmoc=fUDB8r24K1!9Mr@rpAM=;FA$VvL4uVK_hg%E{evreeE9Ir!)N?*}j0eIKIr0QTj!+QzzztV7^pVCJ)MPTka$HR|0#Y0|BSpBb~zLe7lF_%sQ}`gbBr znk(>Za2J&K=c}ccq{@S{enRl1cJNL@ysBqJgQ8A`&hHhxFClfto)XNqA38l_b7rL} zORTyRQAX!YF}Zh{bzk{s0r)!vcTY25)!=*gu>(z&_VzmbE2{IYqetR*uq)+KsbJpf z;f{LX9m-hbq-0XSN9ZeA(0_`eifB2sIRseIT44SmuXpG4S73 zT(Y>r5gJXVV_CG!(W?z_$I&Xb49UA1hZ3}!7=z}=e>zxT;#Zm_dzxq+O|;nqPxJU_ z0v4|8w>qffN-Q2EM6+;`JLIsv^XZmH-<@7}oY4NI{09^~DIDZ_@ml=eNNW_;u~BgT=lLd7g_>sMZh`BfDLV5NABF;=r_NI_9N;>#C?FCloJSJi%K zTv#^Xr+e27fGY`($;Wl{hG+6lyZidcY1g{_ZiwK%az^{C|H2gOKtMb|)R#}VSgWBG z3YgJf>s-uA`ZzTS6-AoFXC^`wRdia>@%bh1>~OQv+wErLuOR^t?D^FDad&BpSL*oDMl=%@5f|VgQHy7X$m?8M?WLNlOco+{av2}^XfCkRN ze5&8ll*b~u$$|>uX3DNjunww)F(3?d~g?N3&$S9>E4&BvWYUEDQpuGrMb zaE#I8Q;Q>ODTg`4FoLYXHtoP;`0K5YI&tsb2ZR+BX+dN8&{l<})Hco17Jc_)iTcvu zZ`Je5j5X4KN_pUDqQ{qJM`XG}Ng|t*B$ik5hK}*X*@HgFCvVR}*G4B_N>kD7dvQ>2*N~ zBtn(YSyYK&xh6Gw$OE5U_@LJ?UKJ+e-#@EhlS9tJu3V?&NE=n@#kO%+qrkX~nUy`? zpcoe9U3YgR-g`<+1iHuPRuIf!rH9Q$_eFvbpWKwA zRCpFFy19~R(?s_N1{{pnI0IOhWVF}Z^OLc$hV7uwlFIu|&(s)-RXoymg=|PIX84F@ zFI6@Ii6lOThW@c3HFZ*vY*R8j zoINKe28g{hnH^r-7lNI$8H>TlpHEDdFJlt5odhx>E~J{imt-BK7D#-oWn6d~=_dJGp{*zkudyx*~@wMr3DT`tr zhhiua4gf}B+%*^e?4#O%yXCOxU;ru-{OjaDPdF#u|H|MKxyW+b)5EvFjF({#(Jd#P zxrX0{KKdksuEuIe_~(w*I!FQg^|;~kF?)jcg`V%%c@vpG9zVvfcC8D$62r7(P6Mxk z973T-Aq|G58!Msl(sgqhnV=1d%5XujM&Um7`b9RoaWi>zk1w&vh`*E2s1|SlC=ioA z+lu_PI%6#gwru{Pwb1E&L#%qwMvW%(Was(+I4A-iNo58(6n>5)!jX-TiK5mA-m~VX zHlfdn6c34Q?yy-5Ko$!e+I^7sxYHoO!z|xCThVxf+)Hxaqi8t!cF(He6hI_kktwS6 z8?FcgyzrHWSHyyGi62jFWA=physv{P2Q}34TVI5npOcBwgWjk4jOL6#lJny)TEcrkrZv71F$3~}?SX{w1NT$>X!Cohw zv}zE8mb=Ri?jl+yzcrTV>m+|ka@F*){7%OJ^u9CzFGO=gVy3J@-<>R#YXfhQRholL zCu#lt{(X~0XMPcpCKqx?SF4WtGxOroJO!r$Q8od37ww=k^63NjN2A3JTw23D@k z=M!E|`v_@XpRD}S!BE#i@a8kp(RV?jt6e3&P>_c5=jB#UU>b+!9&%Atgo{>Cg!{ZPnY$J8`f)YAm@A2T)9>w^NK`7i*BYVNqWi*TJjkNV_0 zGgznb)vW$x3-ZMKMZ&m2;8zMISYt*&bm(c5RjtIvz*=5@&Sm~j6hyaiI5VZTBtvsM zLHpfOE^9@22$O`CVf(vZCw?Bo0a-7z*Wa-x&T(5Wp)fJEae=K-8yg&C|YNAJAE;(dk1#=MmrkFzS#Bm+-@&dMtmaQjZcvq5tmka7ejFkM^ z>EzEUk=lH;$R);$RRU0}$CJA8UHR3XVf1z~#Vf^j39C^4z?!pWJKC@ zIzW?h9-XpW8FQoUf7z-&Ta@J^QBwWkj?Y8!5Ru;a10uX;jf11VUG>vWU%5uKEDQ7HN(p)IH0 za>os#S1ENOTFP5=BX4=!u|Oe5r|Zjdlyfl3&Ed_sdi!<@~8=*iQctxNRc zKheE$+s_4gl0JZZteoRcU5pVudEh}|pIcwV*;1ORq$s%skWOt54=bPQt3@u1T_qX< zkHYN++F9f1!F#gH8sPjdD=T$N>PL_RfH$#&oOEM~iU@|HqnsOkVks3-ABX8dG~9Ds zr21{2Rk+mQ*EX9JCJm{3NkH=HcRvsoSGiSzZ?E`aNlG|gNW>lp(Ed_BX;LgD=!8=iqZ6#>TtN@)FGxI-U~RbHk7>?5`2=O3?EpSV=pBvk!;QF^nG zcSeBDPSHBpW;ruKTT|7oe*<^ z{5DN~P#d)Z0h|HYOya}n!n~aUnKUwJrQHxA3U^Sg_j^?ZQ(*4efi8OLiS;zGHR&Z} zV#+v4vu-vXa!St3L4U4JRu`JElkBN64*F4q?gM(Xwx&nbHNW4a?h`Ua#U!{m{h_y6 ziqYPbH^q$4i$IQ^*_}wO zJnjGp@larw#g9&78Ch7O;cd-%%_BRj0XTvOnWHWevuR$*`05K%zuLlebGeU)OP<@5 zunifGGJn3rl9yl%N#_&R99dNd^+%#+whG(RwtAw|sgt-ow)&wqe{BK3-vG9N1Y4-h zlLHr6WPU#1O+Hm4rAxCS!KA=rFF-Bno@m$8L!IRB@Hu)&b(mvhW~`I9L>o4CI0L5p zDY*BtxopnZ(lly-Pz)p-_I`3grt2Qq)5)l4RH;>{ChRl7Dh*ef_pM9lmS&F<@e7H! zl9;rv&@y34Y9*$TYJ#$;wBJ0&B}&hXOE{A*vms!{GE&ig_iFR}qDT9Qpc>&~UtgQ1 zKM_MQI&Logg}>T)6Fh1-TwGQn6BF;ToFW**fW zU zldT~)w=1()(Nyg;r#L(kWmqQ^YF4gQT(|pbW_qx$m39$O$=@Kzw;jLbDBm;}q-$aY zxnmA%x+f>^#?v*=yA*ui{^ecj0DYKZAb0U4cfO2(g_-p`>YHcv%&0!1MBGisl`WI_ z5g@VX{gzR?8c}xwu9~DWtJk+x>Z*KS4m9IG+K0sBJb_|1Z)!WyChp_(*)lVx!!k;F zu12-7?~Fre2}NNWtzT_4B9HX@osloE&_*BeBQk6_3`DKzcf9BnndrE(q((XZ{!vUK zbtT&z#%?<^Di2exFQZB?w<^0VefL$5LD_)#-y@y(9^_Fau|c29 zBCGYF*vzvWvCfq2r`cxCJfx5csh*op5a?h*b1=_T$P2HwwVw9?>#ayJC$e#;>>MT# zNKGy1C-I>J-Q1O+0_;7<%r5ziHG9in2o4hi@LL!kPxQ+7A-7YHA6RX;Qy9S_ zEw3hD#N4td+5y^g?0ah$YaSU^0WpC^)n{k-V3FHblL9fnzHZJJyE3JIzak6kwd0A8vy+xL+xI=4W!zh-p{g<}j^u9v%HeC%>lkM#k zObpw^Jw%k?J^mXr*55J)A6rbBD3|1XL>u`=#)1CMbx%U!6{wf~NhNYBw(2D2*{9SS z7qRQ3pAu{s;Ho^Wp8%T9D7_>(lzc)+d@BYA7c-N%0uG>kXH*rz`&6ORlrp+9pmH@6l#ZSKvSB$B-lu>#! z=u2foY!$tZQFJaa@|=s0-kHsboUtS93UbJcF22&|%8*j?8@FuBK*|OH$(!u5F2QZ_ z#zrdL~={K)MA*rre8)KgWg7#{zypQ7!^0l6z9r7cnJR; z(|SyNdaKF_EgJ0Tc~r@Nt7JjG-&&~;r^KY6OV&Ri z@h#orr4Jn`D+hs}SqFO0{t35H$d4-C-mer!C!=RF=CcKxZO$wpN9oYsZgPf}L>r@n zKg%B&JQ|CsEB&G2@j|{-exj;I#Y{%__w!rKj!=Pft&QI8MZOMxp&Cfpl!m*me0*8w zGW#iqDernlG*kQ>M}B_WvQ0D#Od~gPAo^J=`G9*W-Tz={(U}Tl= zx-3eHh)Gy)cIN`&-@YHIy|U_Q=~ow@qKA2@RNG^@PokXc#PV#53m46+8&H?LwhR{c z7F7*wdN3uFxo#Q2vwaz)Qbs+rX=?gQbat3o{@u`|aVhD18+3i`Lc>=MV5jJVP@kOm zXeN)+>|*TR5j|~GZ&(V8n_2EF42bbEtJ0RKqo?0*Z%-VYNPJKU+ZnU5SYh?#!S2&# zw667tnh`%8^e9R6HW-C~-J`C*zP7BuY%3a2ubgtaNYKgpIttL!ycw{E`=dDiQ6F|E z1W@17bL;2^;r3Y!jM0mcKMWG^L^oPGr6m$NycbxnkQFNrD?PIN{xC#E1|IosFt}0B zx7?JAS!f>A%o_NFuC@lIkaejXB?dW!h57p50E!GPLv{+AL7n`HHkH8DKfv+&FT0W* z*jI{@Ta^0r0o&+`*_%#3Xa7fmv8H^}q@5dPA{g82j_4fb^>dgnSk+WnFjMg{$TdL+ z`p16UpKZU~T=14kuEC|E_>5^FgZoSz8?S^dEIS*AARiqAVg{-BwZGKyFFqU=w`d39 zB0rb0)>f1V4$mN)3l2KbtI1|H9#6AVh22_FRi13ye=vn}ZjaJ^ng@1$&wL+RQMIwH z-r$g_jh306R~VP7y6ALPOtn+|odT8uD(;&oBjwYLBtQ%R#GY<8F~j;2dn^BFGJdYM z1Qg?DS?U3eQx#c~1Xcbd#!Wk`JeRjSY2lVoL&a59X}g-i;6kB<$eBgQtlUB>?qC%N z07RyW&KU*xC#2s&Fxf^|pwYj|5*{@2 z+9_JfD8MD;AKb$WY*NvWZvjT*FQvA}k&m5XD#@(pF4ghL=j@zVgQf)Ycw zNu3HdC6QB_I@a(uqWQE23ZE1iJvtsC!9MQ`%BxE|FITa&fpL4Q++0qyqx{inyQ=0E zn>HZv8~^!W)KR`t6@d0lX7bReK|B8r%bW_Xlm&j$_>3JP6H;i?+C@r6lY&pbXVN`$ zH*5gD&u6iPJaAh@Abm83m22+rXTE^>mtqh)eJrKXoMPYbn#Ps+@Gm+DFK5Rsx`V4= zBHxPE_mkzUW4+x_X-(qO-UN2DrIxLiQ51e6ZZtb_tsm=pjY*+m>WhSe{>GLM0o(^i za|g6_2{z($n;@KR^9$taUWS_WF{qRYT#q~p~44HV!g zCNbJdftn8Q9-XV9vpX*UlIb!>x$(xrSzCT~0A}x2Z89fK>UZT@h~T|n4+OgT1XBWp zqf;Lw(+n@A{+Ak>`u^i*=d?37G#Oku6X(B}ir~&pR8hfnKQs8Z=-ZSn*D;$JbS$7$ zzD%RlmGg5yrlt8s!f5&3sCMXvVk^|&ukhQXTdDw2LFI)MmvlU&%$}y{uoG-#S3okK zu$7&jWJ=*29}~W4MdBqGS2ve1b~QBps&c)TgG`ZzYI?+`fjvsL-I>J;I4oS7R3q&$ zt~8@w+nAv@jd~S66vZB_rl6^`A+N)d^_0n-5DUg-^~)AE<7PLKnn3;jz2X2^o6+Dv zX0*5;r`Gh?Ch@H$1fZ#huA8RwjXnr_pnuWz_2D9`P9>l;ugmV*$bRBd{7X%b0& z+uzlj6B$mcnPRKQzgiyi~KbBGfq9royA0AE-5cbGOKuOwX2VPZ2S{l zhj>>If{v0e%_)9El+JB#zgF_PAYL5YV9igu6yf>_xsN8KIV`w(10uHQn{k;5QX$y5 zwjf|tYOYl>ozZ+lbOJL#lS2X2nl*F3|Lz-Wc;iKurQUbEfz#!Xc?7 z)Cj|6+}siKAQ}cw`K$KuTX_tw^oOes!qh!th4aTK?Nq07IG9S&TW;wR!c?gbm&E(c zy8Op|&3G@CQxn8wqCQ-lY~2o2L>l#6Gt91m^CN#$?GRC3*eu~MzHCmA@yBsajviX{ zN~J#x;3piCr4csritQU*2DU7=fJVgeUJHGT3b5m>*WWSyNat_1xEj5lMK#-AAD-~s z=n23M*1EZU3@G6$POnQXbof0f00KWoR)}t@1)^b?e8; z#jLe%)%;EKJ^LBP6jjV0+fy0(b}FkpmY_r>oV(InSmSb@9k-`d!7WP%rnozoX{?Wh~2_ZMsd0;iUd-5ScM8w}{&)$v?0=$130jzU)0$s5TV?=w zz30r64aYj(lLHYZX89C5-?-{u9dp4#09KoWz|$GB-3uti)r(A~2lcRm8xs&+u7JV= z9-P{4!MzkU99axE-~GrvGcZ>-7VBZw3AW5AJuvTI!<>rY+viu=-}rIf+Cz!IN4wG3 ztR(BLfls zX|Ul;&y-L?-1!PemAJHtjX1h@DT2$<{AkZjZqUyiVPdcA9@>3EAC`EHg7E0=W43`E zIo(c0^pRS*1;ma#L_Z{eO|M6{oC4Sc=)GuZ@1@8j1NR|>jg?bRUC9`%lOFM z@<_}#&pb81=-a-#Y;9tEVi@yp#hoA^BM4ESbhkx3=ULWyoNFANq)APzoIl-~b$9i5 zSHqTFmL3<9bh=u^@vS!dEW~S9E0Hucq0O9$6$XU$aG>`TnYyej75lb*uO2xBO?u`5 zEDg8H_f#nmsvf3?miPiLm;33do6gZO3Q8(gSHG$1`-L|WBvn~Tg*AJ1&2pq?(yEh} zDD97rg?2TI(dsgFMYo{_b^4&aPu(bYp7kvM!d zv&9be#TIYg6-})^Q63nIM%Q857>#KV&t^P+dXiMRboY51Z@VWhdHt@+Fbgr724F~h z>c`bLnK!>D$vJIx)wk-xZlJ@_!Rq<8W#MNMMl~Z#;VBKmx4qJGl~ zTC3rK3(_}z>*50HUR9=_cp zBq3nV1hBm5yH%+NN;*!zOgAEqGrGk1TMdCpky0b`E_{lxWOzf(y%IIp+RvtXEy1?l zn|PxN(tOng`{g5yOG{Wv;=VIF=7nzs^Aug2HC0p3fKT&0fm+B2)^9U|Tj;xkBz3TIEh# z4D{i=D*M?YFSqZ5xL`qQx?E+k39CP-1uUgDGf|MDriudzZJGY(Or8wHtgk@#bxL3W zVkpcAEEvX`Xs}rAe`u1K-oEW4LpqH>+*)2v;@b%_+UvJHLXOjZf~!{A7XuaZ6ip?N zsn?6(hhIDyeM+b7c-`a01wEuUt~lq7V(os#429Yeb+)Sths@JC6*0 z-ma~8FRd^OJbjFxzg}y+(LU&1U<&R}@is-zpO6BBQDEx*sT7vN;84J^(oL^tMOLz} zAldRb+>HKhclX2Ez9bZ@>u#xNS($nIbL0JCiQuZ-J6Vr@biYIzn2k-scGxPunPbyN zXvGqxH^&m@37R_a9UYk*Jbc{ znz&5=-S%HCdBMqFfixSf7RW20(Y%Msj9GbKk?|~tfQ6-(is4;>lF@p>L9^$$){>)N z(04rpTV_o!MJoJ6nOjlOBF=07VZo2vJ5cT&;Y=N6D{gP{2!CEUCgB`rmq}i-{9i@R z=|W%_AG067eo`UVBf(y$cHV+PeYDXGo-?e7Rx;u0)!ltn=Bw`uLy}&JM}=Z4OMORJ z@BlzNDTgm=D|DN?{j5@?(?xz4{iF4+oyL>iy3D^n4O_vPH|aO1HW9?bW0NXBCe`kBSG0L>~ClBkjv~ zU_OfvFF@-SQE=5XtzNNxlh2KOy=_B_@Ww26af!Ib+<@$3I9O2pwEJ?L!XVLr!pec^ zC5;d6aer1+jrXTCvjV*~pXyzZn&_0sM(VHwj%+^5_Lq2B6^~|?f84ivh7z}ffr#Hz zgKt{BR@?kj=*ID!_T}ziaeptDHSb*TF#TkaWm_KZTiz=#_Y^@S0~T`cYT5 zEKA=3iJNh@>+4|NUU0ni1ow{*Btr8?Y^>`(&4&xBsgTi>8Z(q5AjDyno3?$mYcQ{d3VyP^mcPQQ({tg)+cDoz6}ez z{7fa&J0aX^eAB)X#+utdqLG$*sH`oh(s{Fm^m1|Y*Lp9$5z?XlGk_xUc{sOU;i}~@ z^(6%m?(7+Q?VMNjjNUfel(>5@bK_{eL_mmjv$ZGw4w$2|lBd^u%m;3Wms8h`6doFB zGwB6p+xUUZ%Ffge$LvhsiQNAw6zhhKniu_z3RL&iSZu{Fq{aI}LEtExET0p|2S_pH43=E-%e+z` zKt$})scTdtRp~!2C{n7!w(?d(&tQ~YnaF{4RJ5-|jN%r3h}A1r6GPI;@A`9H<67aL zTlRc!Jc4PV#x@7R-@dut|IFLVRh6)xOpe)cV>Et1Q_2Fx?BH)!_9z;_izYHUU^u=y z81tXINb_%rVNqgt$V+xFY2Fbo7tzSeD3AQdL4?&gYIqCX!PMJF^Uf8uc_M41T~^gO zvO=X-=R{;N$oJ>kPxUT~CQR_1SEualddKd;c`8au%2JXHNU3P*>n&dozP?yi&9cxY zxZ4BaB5>KVmtQ(sa%WdVlsKdxn47YPOYUwDSRY`P#-kAr6kK23~7jf>WJ5NZgP@cxCko)6Ml!eYx)5 z2%53U{`-$A9S4cT3w>qf_a!nRS6+Ou_Mk(?EmHIxk}^=Pb>@W;x_fjs`Ct@FPQrK2 z;_vghI}v@ncDz5=mb~P&=!S3_2Zn(B>jAoPeAj_?@PHIkSdk~$5%MO&tx@KEtqPn` z${$(*%MD8sCr#;m`h5R*-m5xfF=#Y7`qH*hqVokb>Zrf+Qt8TKI0U|M&m7e~f6IefEF+z4N5&8_&_+J9?us3;zLr6l7K3mcKC$ F{$E9^8Lj{T literal 0 HcmV?d00001 diff --git a/docs/native-editor.md b/docs/native-editor.md new file mode 100644 index 0000000..2e09a8e --- /dev/null +++ b/docs/native-editor.md @@ -0,0 +1,78 @@ +# Native Forge2D Editor + +The Windows portable app contains the actual statically linked C++ engine, software renderer and +strict scene/replay parsers. Extract the entire package, then launch `Forge2DEditor.exe`. Keep its +`assets` directory beside it. There is no Python/Node/JDK installation or network dependency. +The first-use status and Help / About explain the controls. The title, help and footer credit Jason +Stys and link his source/contact profile. This unsigned portable candidate is not an OS installer; +system trust prompts, shortcut installation and manual accessibility acceptance are separate work. + +## Complete workflow + +1. Choose **Prepared data > Prepared arena** or **Collision layers**, or File > Open scene. +2. Edit the right-hand scene text, then **Apply scene**. Every existing field is editable, including + bounds, positions, velocity, extents, color, rendering layer, player and category/mask. Invalid + input leaves the previous applied world and saved project intact. The buffer remains editable. +3. Click the canvas. WASD/arrows control the player; Space records the action bit. **Step** performs + one actual engine tick; **Play / Pause** advances fixed 60 Hz ticks with bounded catch-up. The + native clock drops excess wall ticks instead of accumulating an unlimited backlog. **Reset** + returns to the applied authored scene and clears the new recording. +4. **Save project** stores the applied authored scene in `%LOCALAPPDATA%/Forge2DEditor/project.scene`. + Apply pending edits before saving. Running positions/faults are not silently baked into that file. + Restart restores the authored scene paused at tick zero, not a running simulation. +5. File > Import replay loads recorded inputs against the currently applied scene. Play/Step then + consumes those inputs and stops at the final frame. The native editor requires 60 Hz and at most + 36,000 frames. A replay is not an authenticated scene reference: use the corresponding scene. +6. **Export evidence** chooses a new `.evidence` directory beside your selected base name. It writes + `scene.scene`, `inputs.replay`, `frame.ppm`, `snapshot.csv` and `summary.json`. CSV contains only + numeric entity IDs/fields, avoiding scene-name spreadsheet formula interpretation. The summary + records actual tick, state/pixel hash and overlap counts; the full scene accompanies the replay. + +![Actual native custom-scene replay](images/native-editor-play.png) + +![Actual native collision-layer prepared input](images/native-editor-layers.png) + +## Limits and recovery + +The native input budget is 1 MiB, 1,000 entities, and 36,000 input frames (ten minutes at 60 Hz). +The existing library/CLI parser limits remain independent. Empty scenes are supported. Scene v1 +imports use the existing explicit v2 filter migration. World bounds must fully contain every body. +Player inputs override that body's authored velocity; other bodies follow the existing boundary +clamp/bounce model. Rendering layers do not alter collision categories. This editor does not add +physical collision response, triggers, sprite assets, a scripting/plugin system or a commercial +engine asset pipeline. Pathfinding remains the separate tested library API, not an editor navmesh. + +Only one process owns a profile at a time. Project reads use actual bounded regular-file handles; +hardlinks/reparse-point inputs and invalid UTF-8 are refused. Saves use a fresh random exclusive +staging file, flush, then atomic replacement. Data is plaintext under the OS account; another process +with the same user's permissions or an administrator is trusted. No multiuser login is claimed. + +A malformed saved project is preserved. The editor starts a prepared working copy, shows a recovery +notice and requires explicit confirmation before replacing that saved file. Export recovery before +choosing replacement. Closing warns about unapplied/unsaved work. Existing export folders are never +overwritten; a failed export can leave a partial **new** folder, which must be inspected manually. +Back up the profile after clean exit; do not delete the owner file to bypass a running process. + +## Build and actual package acceptance + +In a scoped Visual Studio x64 developer shell with CMake/Ninja: + +```powershell +powershell -NoProfile -File scripts/build-native.ps1 -Output release/my-candidate +python scripts/smoke-native.py release/my-candidate/Forge2DEditor-1.1.0-windows-x64.zip artifacts/native/my-run +``` + +The first command builds the static-runtime native app and all real CTests, verifies embedded +Windows author/version metadata, records Git source/dirty state, and writes a fresh ZIP/sidecar. +The acceptance helper extracts that actual archive into a fresh temporary directory, strips +developer runtimes from its child's PATH, runs three real visible-window launches with only marked +synthetic data, and verifies the executable's compiled source/version against package metadata. +The first exercises editing/play/export, the second checks durable restart, and the third preserves +an intentionally corrupt saved scene while visibly offering a prepared recovery working copy. +Actual native controls and timer events are exercised without external mouse/keyboard automation. + +The read-only native CI job performs the same workflow. Routine PR/push runs retain only bounded +synthetic receipts and screenshots for one day. A full unsigned package is retained only through an +explicit trusted-main manual opt-in. The Windows CodeQL build extracts the Win32 host as well as the +portable core; Linux compilation/analysis, SDL, sanitizer/fuzz, benchmark, coverage and container +gates remain. No successful hosted result or public release is implied by a local candidate. diff --git a/docs/reports/native-editor-2026-11-10.md b/docs/reports/native-editor-2026-11-10.md new file mode 100644 index 0000000..77e64e4 --- /dev/null +++ b/docs/reports/native-editor-2026-11-10.md @@ -0,0 +1,47 @@ +# Native editor validation — 2026-11-10 + +The local 1.1.0 candidate uses the original C++20/C17 engine, scene/replay parsers, collision filters +and software renderer. New `EditorSession` logic keeps the authored scene separate from the running +world and recorded inputs. Default renderer coordinates are unchanged; translated scene origins are +now supported explicitly and independently checked against the same relative pixel image. + +Observed local MSVC Release validation: all **three CTest executables passed**. These comprise the +original ten core groups, four editor-model groups, and real Windows file-boundary cases. Tests +cover invalid/oversized input preserving prior world state; exact independently authored player +coordinates; zero-mask filtering; empty scenes; maximum entity/frame counts; imported replay rate, +completion and live-input override; translated rendering; actual atomic replacement; hardlink, +directory, invalid UTF-8 and oversized file refusal. Coverage percentages from an older report are +not reused for this new source; Linux coverage and full hosted gates remain pending. + +The actual visible native EXE ran with a new marked synthetic profile. Acceptance edited +player coordinates through the real source control, Applied and Saved through the native handlers, +refused invalid input without changing disk/world, captured three right-input steps to **(1520,900)**, +and independently replayed the exported scene/input pair to the actual state hash. Native Play timer +events consumed that three-frame replay and stopped it. The source control's actual multiline row +count and exclusive profile lock were checked. Restart restored authored **(1100,900)** paused at +tick zero. A third launch preserved an intentionally malformed saved scene and displayed the real +recovery notice while offering a prepared working copy. Empty-scene Apply/Step and existing-export +refusal also passed through the real native workflow. All three processes exited normally. The +actual ZIP was separately extracted and passed the same three-launch journey with only Windows +system executables on PATH; its metadata matched the actual EXE's compiled source/dirty/version. +Only this application's owned window was captured, never the desktop. + +The original 20,000-entity benchmark passed unchanged budgets: storage 1.4605 ms, collision 16.7956 ms +and simulation 11.4666 ms in this local run. These headless kernel measurements exclude native GUI, +file/export work and installation. The 360-tick original arena demo passed with eight entities; +state hash `7682307639504695130` and pixel hash `14365382764149795246` describe that specific input. + +Screenshot inspection caught a genuine native EDIT presentation issue: portable LF text did not +display as separate Windows lines. Source display now converts to CRLF; retrieval converts back +before the strict parser. A subsequent actual multiline-control assertion caught the missing reverse +conversion; that was fixed before acceptance passed. The failed evidence remains private; no test +deadline, assertion or core oracle was relaxed. A packaging-shell hash cmdlet availability issue was +fixed with the standard .NET streaming SHA256 API, leaving package hashes independently verifiable. + +Boundaries: this is an unsigned Windows portable app, not an installer, signing proof, populated-user +migration or clean-machine certification. Actual own-window controls/timers were used; a human's +desktop-icon click, file-dialog selection, keyboard accessibility and every OS failure condition were +not automated. Only synthetic profiles were accessed. The app adds no network, hardware, scripting +or physical collision response. Recorded inputs require their matching authored scene. Local files +remain visible to the same OS user/administrator. Historical Word editions retain their original +source baselines until the separately reviewed updated guide is produced. diff --git a/include/forge2d/editor.hpp b/include/forge2d/editor.hpp new file mode 100644 index 0000000..c875392 --- /dev/null +++ b/include/forge2d/editor.hpp @@ -0,0 +1,63 @@ +/** + * File: editor.hpp + * Purpose: Define a bounded editor/play model over the actual scene, world, renderer and replay + * APIs. Symbols and important variable lines are indexed in docs/code-index.md; UI and disk IO stay + * outside. + */ +#pragma once + +#include "forge2d/renderer.hpp" + +#include +#include +#include +#include + +namespace forge2d { + +/** Keep authored scene distinct from the running world and recorded/replayed input history. */ +class EditorSession { + public: + static constexpr std::size_t maximum_input_bytes = 1'048'576U; + static constexpr std::size_t maximum_entities = 1'000U; + static constexpr std::size_t maximum_frames = 36'000U; + + explicit EditorSession(std::string_view scene_text); + void apply_scene(std::string_view text); + void load_replay(std::string_view text); + void reset(); + void play(); + void pause() noexcept; + void step(InputFrame input = {}); + void advance(InputFrame input = {}); + + [[nodiscard]] bool playing() const noexcept { + return playing_; + } + [[nodiscard]] bool reviewing_replay() const noexcept { + return replay_.has_value(); + } + [[nodiscard]] std::size_t replay_remaining() const noexcept; + [[nodiscard]] const Scene& scene() const noexcept { + return scene_; + } + [[nodiscard]] const World& world() const noexcept { + return world_; + } + [[nodiscard]] const Replay& recording() const noexcept { + return recording_; + } + [[nodiscard]] std::string scene_text() const; + [[nodiscard]] std::string replay_text() const; + [[nodiscard]] Image image(std::uint32_t width, std::uint32_t height) const; + + private: + Scene scene_{}; + World world_{}; + Replay recording_{}; + std::optional replay_{}; + std::size_t replay_index_{}; + bool playing_{}; +}; + +} // namespace forge2d diff --git a/include/forge2d/renderer.hpp b/include/forge2d/renderer.hpp index 23a14f2..86a2172 100644 --- a/include/forge2d/renderer.hpp +++ b/include/forge2d/renderer.hpp @@ -38,6 +38,7 @@ class Image { std::vector pixels_{}; }; -void render_world(Image& image, const World& world, Vec2i world_size = {10'000, 10'000}); +void render_world(Image& image, const World& world, Vec2i world_size = {10'000, 10'000}, + Vec2i world_origin = {}); } // namespace forge2d diff --git a/scripts/build-native.ps1 b/scripts/build-native.ps1 new file mode 100644 index 0000000..20c1c11 --- /dev/null +++ b/scripts/build-native.ps1 @@ -0,0 +1,47 @@ +# File: build-native.ps1 +# Purpose: Build/package a static-runtime native Windows editor; never install or touch user profiles. +param([string]$Output = 'release/native-candidate') +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest +$Repo = Split-Path -Parent $PSScriptRoot +$Destination = [System.IO.Path]::GetFullPath((Join-Path $Repo $Output)) +if (-not $Destination.StartsWith(($Repo + [System.IO.Path]::DirectorySeparatorChar), [StringComparison]::OrdinalIgnoreCase)) { + throw 'Package output must remain inside this repository.' +} +if (Test-Path -LiteralPath $Destination) { throw 'Use a fresh package output; existing candidates are preserved.' } +cmake -S $Repo -B (Join-Path $Repo '.runtime/native-build') -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded +if ($LASTEXITCODE -ne 0) { throw 'Native configuration failed.' } +cmake --build (Join-Path $Repo '.runtime/native-build') --parallel 2 +if ($LASTEXITCODE -ne 0) { throw 'Native build failed.' } +ctest --test-dir (Join-Path $Repo '.runtime/native-build') --output-on-failure +if ($LASTEXITCODE -ne 0) { throw 'Native/core tests failed.' } +$Package = Join-Path $Destination 'Forge2DEditor' +New-Item -ItemType Directory -Path (Join-Path $Package 'assets') -Force | Out-Null +Copy-Item -LiteralPath (Join-Path $Repo '.runtime/native-build/Forge2DEditor.exe') -Destination $Package +Copy-Item -LiteralPath (Join-Path $Repo 'LICENSE') -Destination $Package +foreach ($Name in @('arena.scene', 'collision-layers.scene')) { + Copy-Item -LiteralPath (Join-Path $Repo "assets/$Name") -Destination (Join-Path $Package 'assets') +} +$Metadata = (Get-Item -LiteralPath (Join-Path $Package 'Forge2DEditor.exe')).VersionInfo +if ($Metadata.CompanyName -ne 'Jason Stys' -or $Metadata.ProductVersion -ne '1.1.0') { throw 'Native author/version mismatch.' } +$Source = (git -C $Repo -c "safe.directory=$Repo" rev-parse HEAD).Trim() +if ($LASTEXITCODE -ne 0 -or $Source -notmatch '^[0-9a-f]{40}$') { throw 'Source identity unavailable.' } +$Dirty = @(git -C $Repo -c "safe.directory=$Repo" status --porcelain).Count -ne 0 +@{schema=1; version='1.1.0'; source=$Source; dirty=$Dirty; format='Windows portable'; author='Jason Stys'} | + ConvertTo-Json | Set-Content -LiteralPath (Join-Path $Package 'RELEASE.json') -Encoding utf8 +@' +Forge2D Editor 1.1.0 - Jason Stys +Extract this entire folder, then launch Forge2DEditor.exe. No IDE, compiler, Python or Node required. +Help / About describes all controls and scene fields. Prepared data is inside this actual editor. +Your project is saved under your OS-local Forge2DEditor profile, outside this program folder. +No hardware, network, authentication or physical collision-response guarantee. Unsigned portable app. +Source and contact: https://github.com/JasonStys/forge2d-engine +'@ | Set-Content -LiteralPath (Join-Path $Package 'README.txt') -Encoding utf8 +$Archive = Join-Path $Destination 'Forge2DEditor-1.1.0-windows-x64.zip' +Compress-Archive -Path (Join-Path $Package '*') -DestinationPath $Archive -CompressionLevel Optimal +$Stream = [System.IO.File]::OpenRead($Archive) +$Hasher = [System.Security.Cryptography.SHA256]::Create() +try { $Hash = [BitConverter]::ToString($Hasher.ComputeHash($Stream)).Replace('-', '').ToLowerInvariant() } +finally { $Stream.Dispose(); $Hasher.Dispose() } +"$Hash $([System.IO.Path]::GetFileName($Archive))" | Set-Content -LiteralPath ($Archive + '.sha256') -Encoding ascii +Write-Output $Archive diff --git a/scripts/generate-code-index.mjs b/scripts/generate-code-index.mjs index fa4daeb..ed9a3e7 100644 --- a/scripts/generate-code-index.mjs +++ b/scripts/generate-code-index.mjs @@ -10,8 +10,8 @@ import { fileURLToPath } from "node:url"; const root = resolve(dirname(fileURLToPath(import.meta.url)), ".."); const outputPath = join(root, "docs", "code-index.md"); -const supportedExtensions = new Set([".c", ".cpp", ".h", ".hpp", ".mjs", ".sh"]); -const excludedDirectories = new Set([".git", ".cache", "build", "coverage", "dist", "out"]); +const supportedExtensions = new Set([".c", ".cpp", ".h", ".hpp", ".mjs", ".sh", ".ps1", ".py", ".rc"]); +const excludedDirectories = new Set([".git", ".cache", ".runtime", "artifacts", "release", "build", "coverage", "dist", "out"]); const typePattern = /^\s*(?:class|struct|enum(?:\s+class)?)\s+([A-Za-z_][\w]*)/; const functionPattern = /^\s*(?:\[\[[^\]]+\]\]\s*)?(?:(?:constexpr|explicit|inline|static|virtual)\s+)*(?:[\w:<>,*&]+\s+)+((?:[A-Za-z_][\w]*::)*(?:~?[A-Za-z_][\w]*|operator(?:<=>|==|\[\]|\(\)|[-+*/=<>]+)))\s*\(/; const qualifiedConstructorPattern = /^\s*((?:[A-Za-z_][\w]*::)+~?[A-Za-z_][\w]*)\s*\(/; @@ -35,6 +35,14 @@ function declarations(path) { const lines = readFileSync(path, "utf8").split(/\r?\n/); const knownTypes = new Set(lines.flatMap((line) => line.match(typePattern)?.[1] ?? [])); return lines.flatMap((line, index) => { + if (extension === ".py") { + const match = line.match(/^\s*(?:def|class)\s+([A-Za-z_][\w]*)/) ?? line.match(/^([A-Z_][\w]*)\s*=/); + return match ? [{ line: index + 1, name: match[1] }] : []; + } + if (extension === ".ps1") { + const match = line.match(/^\s*function\s+([\w-]+)/i) ?? line.match(/^\s*\$([\w]+)\s*=/); + return match ? [{ line: index + 1, name: match[1] }] : []; + } if (extension === ".mjs") { const match = line.match(/\b(?:function|class)\s+([A-Za-z_$][\w$]*)/) ?? line.match(/\b(?:const|let)\s+([A-Za-z_$][\w$]*)\b/); diff --git a/scripts/smoke-native.py b/scripts/smoke-native.py new file mode 100644 index 0000000..1304d8e --- /dev/null +++ b/scripts/smoke-native.py @@ -0,0 +1,93 @@ +"""File: smoke-native.py. Purpose: run actual play/restart/recovery with a marked synthetic profile. + +Functions/variables and exact source lines are listed in docs/code-index.md. This harness uses +the editor's own event handlers, real engine, file IO and visible window, not external OS input. +It never reads the default user profile or installs shortcuts. Timeouts are failures, not retries. +""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import os +from pathlib import Path +import subprocess +import tempfile +import zipfile + + +def run(executable: Path, output: Path, metadata: dict | None = None) -> None: + """Bind acceptance to one packaged EXE and fresh root; preserve all three actual launch results.""" + executable = executable.resolve(strict=True) + output = output.resolve() + output.mkdir(parents=True, exist_ok=False) + (output / "acceptance.marker").write_text("forge2d-owned-native-test\n", encoding="utf-8", newline="\n") + environment = {key: os.environ[key] for key in ("SYSTEMROOT", "WINDIR", "TEMP", "TMP") if key in os.environ} + environment.update(PATH=str(Path(os.environ.get("SYSTEMROOT", "C:/Windows")) / "System32"), + FORGE2D_ACCEPTANCE="1") + stages = [] + with tempfile.TemporaryDirectory(prefix="forge2d-native-cwd-") as cwd: + for phase in (1, 2, 3): + if phase == 3: + (output / "profile" / "project.scene").write_text("invalid saved scene\n", encoding="utf-8", newline="\n") + result = subprocess.run( + [str(executable), "--acceptance-root", str(output), "--acceptance-phase", str(phase)], + cwd=cwd, + env=environment, + timeout=45, + check=False, + ) + if result.returncode != 0: + raise RuntimeError(f"Native acceptance phase {phase} exited {result.returncode}.") + stages.append(json.loads((output / f"phase-{phase}.json").read_text(encoding="utf-8"))) + if metadata is not None: + if (metadata["source"] != stages[0]["source"] or metadata["dirty"] is not stages[0]["sourceDirty"] + or metadata["version"] != stages[0]["version"]): + raise RuntimeError("Packaged metadata does not match the actual compiled source/version.") + if os.environ.get("CI") and metadata["dirty"] is not False: + raise RuntimeError("Hosted native acceptance requires a clean source checkout.") + summary = json.loads((output / "evidence" / "summary.json").read_text(encoding="utf-8")) + if summary["recordedFrames"] != 3 or summary["tick"] != 3: + raise RuntimeError("Export did not retain the actual three-step engine execution.") + for name in ("editor-play.png", "editor-layers.png"): + image = output / name + if not image.read_bytes().startswith(b"\x89PNG\r\n\x1a\n") or image.stat().st_size < 10_000: + raise RuntimeError("Native screenshot missing or implausibly empty.") + receipt = { + "schema": 1, + "version": "1.1.0", + "executableSha256": hashlib.sha256(executable.read_bytes()).hexdigest(), + "phases": stages, + "export": summary, + "scope": "Actual visible native windows and own-handler input; no external mouse/shortcut or clean-machine proof.", + } + (output / "native-acceptance.json").write_text(json.dumps(receipt, indent=2) + "\n", encoding="utf-8") + if (output / "profile" / "project.scene").read_bytes() != b"invalid saved scene\n": + raise RuntimeError("Corrupt-profile recovery overwrote the preserved synthetic input.") + print(json.dumps({"conclusion": "success", "launches": 3, "recordedInputs": 3, "output": str(output)})) + + +def main() -> None: + """Use only caller-named EXE/ZIP and a new output directory; archives are this build's outputs.""" + parser = argparse.ArgumentParser() + parser.add_argument("executable", type=Path) + parser.add_argument("output", type=Path) + args = parser.parse_args() + if args.executable.suffix.lower() == ".zip": + with tempfile.TemporaryDirectory(prefix="forge2d-extracted-") as folder: + with zipfile.ZipFile(args.executable) as package: + names = set(package.namelist()) + allowed = {"Forge2DEditor.exe", "LICENSE", "RELEASE.json", "README.txt", + "assets/arena.scene", "assets/collision-layers.scene"} + if names - {"assets/"} != allowed or sum(row.file_size for row in package.infolist()) > 30_000_000: + raise ValueError("Unexpected portable archive members or size.") + package.extractall(folder) + metadata = json.loads((Path(folder) / "RELEASE.json").read_text(encoding="utf-8-sig")) + run(Path(folder) / "Forge2DEditor.exe", args.output, metadata) + else: + run(args.executable, args.output) + + +if __name__ == "__main__": + main() diff --git a/scripts/validate-repository.mjs b/scripts/validate-repository.mjs index 8f60818..3813f02 100644 --- a/scripts/validate-repository.mjs +++ b/scripts/validate-repository.mjs @@ -16,8 +16,8 @@ const requiredFiles = [ "docs/testing.md", "docs/adr/0001-headless-core-and-optional-sdl3.md", "docs/reports/benchmark.md", "docs/reports/test-summary.md", "docs/reports/validation.md", ]; -const headerExtensions = new Set([".c", ".cpp", ".h", ".hpp", ".mjs", ".sh"]); -const excludedDirectories = new Set([".git", ".cache", "build", "coverage", "dist", "out"]); +const headerExtensions = new Set([".c", ".cpp", ".h", ".hpp", ".mjs", ".sh", ".ps1", ".py", ".rc"]); +const excludedDirectories = new Set([".git", ".cache", ".runtime", "artifacts", "release", "build", "coverage", "dist", "out"]); /** Recursively list authored files while excluding generated output and dependencies. */ function walk(directory) { diff --git a/scripts/verify.sh b/scripts/verify.sh index cabe4a0..1815369 100644 --- a/scripts/verify.sh +++ b/scripts/verify.sh @@ -13,9 +13,9 @@ mapfile -t SOURCES < <(find apps benchmarks fuzz include platform src tests \ clang-format --dry-run --Werror "${SOURCES[@]}" cmake -S . -B "${BUILD_DIR}" -G Ninja -DCMAKE_BUILD_TYPE=Release cmake --build "${BUILD_DIR}" --parallel -clang-tidy -p "${BUILD_DIR}" src/collision.cpp src/pathfinding.cpp src/replay.cpp src/scene.cpp \ +clang-tidy -p "${BUILD_DIR}" src/editor.cpp src/collision.cpp src/pathfinding.cpp src/replay.cpp src/scene.cpp \ src/software_renderer.cpp src/world.cpp apps/forge2d_arena.cpp tests/test_main.cpp \ - benchmarks/benchmark.cpp + tests/test_editor.cpp benchmarks/benchmark.cpp ctest --test-dir "${BUILD_DIR}" --output-on-failure "${BUILD_DIR}/forge2d_benchmark" | tee docs/reports/generated/benchmark.json "${BUILD_DIR}/forge2d_arena" assets/arena.scene out/verify diff --git a/src/editor.cpp b/src/editor.cpp new file mode 100644 index 0000000..449832a --- /dev/null +++ b/src/editor.cpp @@ -0,0 +1,122 @@ +/** + * File: editor.cpp + * Purpose: Apply scene changes transactionally and run bounded real engine/replay workflows. + * Symbols and important variable lines are indexed in docs/code-index.md; no platform IO occurs + * here. + */ +#include "forge2d/editor.hpp" + +#include +#include + +namespace forge2d { + +EditorSession::EditorSession(std::string_view scene_text) { + apply_scene(scene_text); +} + +void EditorSession::apply_scene(std::string_view text) { + if (text.size() > maximum_input_bytes) { + throw std::invalid_argument("Editor scene input exceeds 1 MiB"); + } + auto next_scene = parse_scene(text); + if (next_scene.entities.size() > maximum_entities) { + throw std::invalid_argument("Editor scenes are limited to 1000 entities"); + } + auto next_world = World::from_scene(next_scene); + Replay next_recording; + next_recording.frames.reserve(maximum_frames); + scene_ = std::move(next_scene); + world_ = std::move(next_world); + recording_ = std::move(next_recording); + replay_.reset(); + replay_index_ = 0U; + playing_ = false; +} + +void EditorSession::reset() { + auto next_world = World::from_scene(scene_); + world_ = std::move(next_world); + recording_.frames.clear(); + replay_.reset(); + replay_index_ = 0U; + playing_ = false; +} + +void EditorSession::load_replay(std::string_view text) { + if (text.size() > maximum_input_bytes) { + throw std::invalid_argument("Editor replay input exceeds 1 MiB"); + } + auto replay = parse_replay(text); + if (replay.tick_rate != 60U || replay.frames.size() > maximum_frames) { + throw std::invalid_argument("Editor replay requires 60 Hz and at most 36000 frames"); + } + auto next_world = World::from_scene(scene_); + Replay next_recording{replay.seed, replay.tick_rate, {}}; + next_recording.frames.reserve(maximum_frames); + world_ = std::move(next_world); + recording_ = std::move(next_recording); + replay_ = std::move(replay); + replay_index_ = 0U; + playing_ = false; +} + +void EditorSession::play() { + if (recording_.frames.size() >= maximum_frames || (replay_ && replay_remaining() == 0U)) { + throw std::invalid_argument("Recording/replay is complete; reset or load a new input"); + } + playing_ = true; +} + +void EditorSession::pause() noexcept { + playing_ = false; +} + +std::size_t EditorSession::replay_remaining() const noexcept { + return replay_ ? replay_->frames.size() - replay_index_ : 0U; +} + +void EditorSession::step(InputFrame input) { + if (recording_.frames.size() >= maximum_frames) { + playing_ = false; + throw std::invalid_argument("Recording limit reached; export before resetting"); + } + if (replay_) { + if (replay_remaining() == 0U) { + playing_ = false; + throw std::invalid_argument("Replay is complete"); + } + input = replay_->frames[replay_index_]; + } + if (input.move_x < -1 || input.move_x > 1 || input.move_y < -1 || input.move_y > 1) { + throw std::invalid_argument("Movement inputs must be in -1..1"); + } + world_.step(input); + recording_.frames.push_back(input); + if (replay_) { + ++replay_index_; + if (replay_remaining() == 0U) + playing_ = false; + } +} + +void EditorSession::advance(InputFrame input) { + if (playing_) + step(input); +} + +std::string EditorSession::scene_text() const { + return serialize_scene(scene_); +} +std::string EditorSession::replay_text() const { + return serialize_replay(recording_); +} + +Image EditorSession::image(std::uint32_t width, std::uint32_t height) const { + Image image{width, height}; + const Vec2i extent{scene_.maximum.x - scene_.minimum.x, scene_.maximum.y - scene_.minimum.y}; + render_world(image, world_, extent, scene_.minimum); + return image; +} + +} // namespace forge2d diff --git a/src/software_renderer.cpp b/src/software_renderer.cpp index 0f9b8fe..eca80b6 100644 --- a/src/software_renderer.cpp +++ b/src/software_renderer.cpp @@ -92,24 +92,27 @@ std::uint64_t Image::pixel_hash() const noexcept { return hash; } -void render_world(Image& image, const World& world, Vec2i world_size) { +void render_world(Image& image, const World& world, Vec2i world_size, Vec2i world_origin) { if (world_size.x <= 0 || world_size.y <= 0) { throw std::invalid_argument("render world size must be positive"); } image.clear(0x101827FFU); for (const auto& entity : world.snapshot()) { - const auto left = project_coordinate( - static_cast(entity.transform.position.x) - entity.body.half_extent.x, - world_size.x, image.width()); - const auto right = project_coordinate( - static_cast(entity.transform.position.x) + entity.body.half_extent.x, - world_size.x, image.width()); + const auto left = + project_coordinate(static_cast(entity.transform.position.x) - + world_origin.x - entity.body.half_extent.x, + world_size.x, image.width()); + const auto right = + project_coordinate(static_cast(entity.transform.position.x) - + world_origin.x + entity.body.half_extent.x, + world_size.x, image.width()); const auto top = project_coordinate(static_cast(entity.transform.position.y) - - entity.body.half_extent.y, + world_origin.y - entity.body.half_extent.y, world_size.y, image.height()); - const auto bottom = project_coordinate( - static_cast(entity.transform.position.y) + entity.body.half_extent.y, - world_size.y, image.height()); + const auto bottom = + project_coordinate(static_cast(entity.transform.position.y) - + world_origin.y + entity.body.half_extent.y, + world_size.y, image.height()); image.fill_rect(left, top, right, bottom, entity.sprite.rgba); } } diff --git a/tests/test_editor.cpp b/tests/test_editor.cpp new file mode 100644 index 0000000..9782e43 --- /dev/null +++ b/tests/test_editor.cpp @@ -0,0 +1,179 @@ +/** + * File: test_editor.cpp + * Purpose: Independently verify editor scene/replay transitions, input limits and actual rendering. + * Symbols and important variable lines are indexed in docs/code-index.md; all fixtures are + * synthetic. + */ +#include "forge2d/editor.hpp" + +#include +#include +#include +#include +#include +#include +#include + +namespace { +constexpr std::string_view scene_text = "FORGE2D_SCENE 2\nbounds 0 0 10000 10000\nentities 2\n" + "entity player 1000 1000 0 0 100 100 16711935 10 1 1 2\n" + "entity zone 1150 1000 0 0 100 100 4278190335 5 0 2 1\n"; + +void require(bool condition, const char* message) { + if (!condition) + throw std::runtime_error(message); +} +template void rejects(Function&& operation, const char* message) { + try { + operation(); + } catch (const std::exception&) { + return; + } + throw std::runtime_error(message); +} + +void test_authored_input_and_replay() { + forge2d::EditorSession session{scene_text}; + require(!session.playing() && session.world().tick() == 0U, "editor must begin paused"); + require(session.world().collision_pairs().size() == 1U, "authored compatible zones overlap"); + session.advance({1, 0, false}); + require(session.world().tick() == 0U, "paused timer cannot advance the actual world"); + session.play(); + const std::array inputs{ + {{1, 0, false}, {1, 0, true}, {0, 1, false}, {0, 0, false}}}; + for (const auto input : inputs) + session.advance(input); + session.pause(); + const auto snapshot = session.world().snapshot(); + const auto player = std::find_if(snapshot.begin(), snapshot.end(), + [](const auto& entity) { return entity.player; }); + require(player != snapshot.end() && player->transform.position == forge2d::Vec2i{1280, 1140}, + "four authored player inputs must yield x1280/y1140"); + require(session.recording().frames == + std::vector(inputs.begin(), inputs.end()), + "recording must contain actual applied inputs"); + const auto expected = session.world().state_hash(); + const auto replay = session.replay_text(); + session.load_replay(replay); + require(session.reviewing_replay() && session.replay_remaining() == 4U && !session.playing(), + "replay load must reset and pause actual world"); + session.play(); + for (std::size_t index = 0; index < inputs.size(); ++index) + session.advance({-1, -1, true}); + require(session.world().state_hash() == expected && !session.playing(), + "playback must ignore live input and exactly reproduce original state"); + require(session.replay_remaining() == 0U, "completed replay must have no invented frames"); + rejects([&] { session.play(); }, "completed replay must refuse resumed play"); + rejects([&] { session.step(); }, "completed replay must refuse invented manual frames"); + session.reset(); + require(!session.reviewing_replay() && session.recording().frames.empty() && + session.world().tick() == 0U, + "reset restores authored scene and clears transient input history"); +} + +void test_apply_is_transactional() { + forge2d::EditorSession session{scene_text}; + session.step({1, 0, false}); + const auto hash = session.world().state_hash(); + const auto canonical = session.scene_text(); + rejects([&] { session.apply_scene("bad scene"); }, "invalid text must be refused"); + rejects( + [&] { + session.apply_scene(std::string(forge2d::EditorSession::maximum_input_bytes + 1U, 'x')); + }, + "oversized source must be refused"); + auto invalid = forge2d::parse_scene(scene_text); + invalid.entities[0].transform.position = {0, 0}; + rejects([&] { session.apply_scene(forge2d::serialize_scene(invalid)); }, + "engine must reject a body that does not fit bounds"); + require(session.scene_text() == canonical && session.world().state_hash() == hash && + session.recording().frames.size() == 1U, + "refused apply must preserve authored scene and running/recorded state"); + rejects([&] { session.step({2, 0, false}); }, "invalid live movement must be refused"); + require(session.world().state_hash() == hash, "invalid movement must not mutate actual world"); + auto updated = forge2d::parse_scene(scene_text); + updated.entities[0].body.filter.mask = 0U; + session.apply_scene(forge2d::serialize_scene(updated)); + require(session.world().collision_pairs().empty(), + "applying edited scene must change actual collision filters"); + require(session.world().tick() == 0U && session.recording().frames.empty(), + "accepted edit starts a new paused run"); + session.apply_scene("FORGE2D_SCENE 2\nbounds 0 0 1000 1000\nentities 0\n"); + require(session.world().entity_count() == 0U, "empty project is a valid editor boundary"); +} + +void test_replay_limits() { + forge2d::EditorSession session{scene_text}; + const auto old_hash = session.world().state_hash(); + rejects([&] { session.load_replay("bad replay"); }, "malformed replay must be refused"); + rejects( + [&] { + session.load_replay(std::string(forge2d::EditorSession::maximum_input_bytes + 1U, 'x')); + }, + "oversized replay must be refused"); + forge2d::Replay replay{0U, 120U, {}}; + rejects([&] { session.load_replay(forge2d::serialize_replay(replay)); }, + "native editor must not reinterpret a different tick rate"); + replay.tick_rate = 60U; + replay.frames.resize(forge2d::EditorSession::maximum_frames + 1U); + rejects([&] { session.load_replay(forge2d::serialize_replay(replay)); }, + "native replay cap must be checked before state mutation"); + require(session.world().state_hash() == old_hash, "refused replay must preserve project state"); + replay.frames.clear(); + session.load_replay(forge2d::serialize_replay(replay)); + rejects([&] { session.play(); }, "zero-frame replay must remain explicit and paused"); + session.reset(); + for (std::size_t index = 0; index < forge2d::EditorSession::maximum_frames; ++index) + session.step(); + rejects([&] { session.step(); }, "recording must not silently discard input on overflow"); + rejects([&] { session.play(); }, "full recording must not restart without reset/export"); + require(session.world().tick() == forge2d::EditorSession::maximum_frames, + "failed overflow must not advance simulation"); +} + +void test_entities_and_offset_rendering() { + forge2d::EditorSession session{scene_text}; + auto scene = forge2d::parse_scene(scene_text); + const auto prototype = scene.entities.back(); + scene.entities.clear(); + for (std::size_t index = 0; index < forge2d::EditorSession::maximum_entities + 1U; ++index) { + auto entity = prototype; + entity.name = "entity_" + std::to_string(index); + scene.entities.push_back(entity); + } + rejects([&] { session.apply_scene(forge2d::serialize_scene(scene)); }, + "native entity budget must be enforced"); + scene.entities.pop_back(); + session.apply_scene(forge2d::serialize_scene(scene)); + require(session.world().entity_count() == forge2d::EditorSession::maximum_entities, + "exact native entity boundary must remain accepted"); + session.apply_scene(scene_text); + const auto origin_image = session.image(100U, 100U); + scene = forge2d::parse_scene(scene_text); + scene.minimum = {-5000, -5000}; + scene.maximum = {5000, 5000}; + for (auto& entity : scene.entities) { + entity.transform.position.x -= 5000; + entity.transform.position.y -= 5000; + } + session.apply_scene(forge2d::serialize_scene(scene)); + require(session.image(100U, 100U).pixel_hash() == origin_image.pixel_hash(), + "translated world origins must preserve actual framebuffer geometry"); + rejects([&] { static_cast(session.image(0U, 100U)); }, + "invalid framebuffers must remain rejected"); +} +} // namespace + +int main() { + try { + test_authored_input_and_replay(); + test_apply_is_transactional(); + test_replay_limits(); + test_entities_and_offset_rendering(); + std::cout << "Editor model: 4 independent test groups passed\n"; + return 0; + } catch (const std::exception& error) { + std::cerr << error.what() << '\n'; + return 1; + } +} diff --git a/tests/test_editor_files.cpp b/tests/test_editor_files.cpp new file mode 100644 index 0000000..e601be6 --- /dev/null +++ b/tests/test_editor_files.cpp @@ -0,0 +1,81 @@ +/** + * File: test_editor_files.cpp + * Purpose: Exercise real Windows handles, bounded UTF-8 reads, atomic replacement and hardlink + * refusal. Functions/variables and locations: docs/code-index.md. Only a new temporary test + * directory is used. + */ +#include "../apps/editor_files.hpp" + +#include +#include +#include + +namespace { +void require(bool value) { + if (!value) { + throw std::runtime_error("native file invariant failed"); + } +} + +template void refused(Operation operation) { + bool rejected{}; + try { + operation(); + } catch (const std::exception&) { + rejected = true; + } + require(rejected); +} +} // namespace + +int main() { + using namespace forge2d::desktop; + wchar_t temporary[MAX_PATH]{}; + wchar_t name[MAX_PATH]{}; + if (GetTempPathW(MAX_PATH, temporary) == 0U || + GetTempFileNameW(temporary, L"f2d", 0, name) == 0U) { + return 2; + } + DeleteFileW(name); + const std::filesystem::path root{name}; + try { + ensure_profile(root); + const auto file = root / L"scene.scene"; + atomic_text(file, "first\n"); + require(read_text(file) == "first\n"); + atomic_text(file, "replacement\n"); + require(read_text(file) == "replacement\n"); + const auto linked = root / L"linked.scene"; + require(CreateHardLinkW(linked.c_str(), file.c_str(), nullptr) != FALSE); + refused([&] { (void)read_text(file); }); + refused([&] { atomic_text(file, "must not replace"); }); + require(DeleteFileW(linked.c_str()) != FALSE); + require(read_text(file) == "replacement\n"); + refused([&] { (void)read_text(root); }); + refused([&] { (void)read_text(root / L"missing.scene"); }); + { + std::ofstream oversized{root / L"large.scene", std::ios::binary}; + oversized << std::string(1'048'577U, 'x'); + } + refused([&] { (void)read_text(root / L"large.scene"); }); + refused([&] { atomic_text(file, std::string(1'048'577U, 'x')); }); + require(read_text(file) == "replacement\n"); + atomic_text(file, std::string{"\xff\xfe", 2}); + refused([&] { (void)read_text(file); }); + const auto unicode = std::string{"unit \xe2\x86\x92 value"}; + require(utf8(wide(unicode)) == unicode); + atomic_text(file, "final\n"); + require(read_text(file) == "final\n"); + for (const auto& member : std::filesystem::directory_iterator(root)) { + require(member.path().filename().wstring().find(L".tmp-") == std::wstring::npos); + } + std::filesystem::remove_all(root); + std::cout + << "Native file boundary: actual save/replace/read/link/UTF-8/budget cases passed.\n"; + return 0; + } catch (const std::exception& error) { + std::cerr << error.what() << '\n'; + std::filesystem::remove_all(root); + return 1; + } +} From 33c4a6f26fcc9421769435b92a6565c20197afdb Mon Sep 17 00:00:00 2001 From: JasonStys Date: Tue, 10 Nov 2026 18:17:02 -0800 Subject: [PATCH 2/3] Fix Unicode MinGW linking and build all container test targets --- .github/workflows/ci.yml | 10 +++++----- CMakeLists.txt | 3 +++ Dockerfile | 2 +- docs/reports/native-editor-2026-11-10.md | 9 +++++++++ 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4512165..44b121a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,28 +69,28 @@ jobs: if-no-files-found: error windows: - name: Windows MSVC + name: Windows MinGW (MSVC also tested by native package job) runs-on: windows-latest steps: - name: Check out source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Configure and build run: | - cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release + cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ cmake --build build --parallel 2 - name: Run tests and benchmark run: | ctest --test-dir build --output-on-failure New-Item -ItemType Directory -Force docs/reports/generated | Out-Null - ./build/forge2d_benchmark.exe | Tee-Object docs/reports/generated/benchmark-msvc.json + ./build/forge2d_benchmark.exe | Tee-Object docs/reports/generated/benchmark-mingw.json ./build/forge2d_arena.exe assets/arena.scene out/ci - name: Upload Windows evidence if: always() uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: - name: windows-msvc-evidence + name: windows-mingw-evidence path: | - docs/reports/generated/benchmark-msvc.json + docs/reports/generated/benchmark-mingw.json out/ci if-no-files-found: error diff --git a/CMakeLists.txt b/CMakeLists.txt index a28899f..27e3b63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,6 +111,9 @@ if(WIN32) target_link_libraries(Forge2DEditor PRIVATE Forge2D::Core comdlg32 gdiplus bcrypt shell32 ole32) target_compile_definitions(Forge2DEditor PRIVATE UNICODE _UNICODE FORGE2D_NATIVE_SOURCE="${FORGE2D_NATIVE_SOURCE}" FORGE2D_NATIVE_DIRTY=${FORGE2D_NATIVE_DIRTY}) + if(MINGW) + target_link_options(Forge2DEditor PRIVATE -municode) + endif() forge2d_set_warnings(Forge2DEditor) add_custom_command(TARGET Forge2DEditor POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory diff --git a/Dockerfile b/Dockerfile index 578ead4..790952b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,7 @@ RUN apt-get update \ WORKDIR /source COPY . . RUN cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release \ - && cmake --build build --target forge2d_arena forge2d_tests forge2d_benchmark --parallel \ + && cmake --build build --target forge2d_arena forge2d_tests forge2d_editor_tests forge2d_benchmark --parallel \ && ctest --test-dir build --output-on-failure \ && ./build/forge2d_benchmark diff --git a/docs/reports/native-editor-2026-11-10.md b/docs/reports/native-editor-2026-11-10.md index 77e64e4..9fc1e77 100644 --- a/docs/reports/native-editor-2026-11-10.md +++ b/docs/reports/native-editor-2026-11-10.md @@ -38,6 +38,15 @@ conversion; that was fixed before acceptance passed. The failed evidence remains deadline, assertion or core oracle was relaxed. A packaging-shell hash cmdlet availability issue was fixed with the standard .NET streaming SHA256 API, leaving package hashes independently verifiable. +The first PR integration at `03c0175` passed actual Windows extracted-package acceptance and the +Linux GCC/Clang, coverage, sanitizers/fuzz, clang-tidy, SDL and repository lanes. Two other Windows +jobs selected MinGW despite an old MSVC label; their Unicode `wWinMain` link required `-municode`. +The original Windows compiler lane is now explicitly GCC/MinGW and labelled accordingly; actual +MSVC remains exercised by native packaging. The container's explicit target list also omitted the +new editor-model test before running all CTests; that target is now built. These were real build/ +workflow integration faults, corrected without disabling tests. Corrective hosted results remain +pending; Docker on the PC was not changed or used. + Boundaries: this is an unsigned Windows portable app, not an installer, signing proof, populated-user migration or clean-machine certification. Actual own-window controls/timers were used; a human's desktop-icon click, file-dialog selection, keyboard accessibility and every OS failure condition were From 003725e10deddf502103f1dd998e495ecc053f5e Mon Sep 17 00:00:00 2001 From: JasonStys Date: Tue, 10 Nov 2026 19:24:39 -0800 Subject: [PATCH 3/3] Preserve genuine baseline CodeQL job and add native Windows analysis --- .github/workflows/codeql.yml | 30 +++++++++++++++++------- docs/reports/native-editor-2026-11-10.md | 8 +++++++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 92c3f8a..888fae4 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -17,13 +17,8 @@ permissions: jobs: analyze: - name: Analyze C and C++ (${{ matrix.os }}) - runs-on: ${{ matrix.os }} - timeout-minutes: 20 - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest] + name: Analyze C and C++ + runs-on: ubuntu-latest steps: - name: Check out source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -38,5 +33,24 @@ jobs: cmake --build build --parallel 2 - name: Analyze uses: github/codeql-action/analyze@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3; coordinated version + + analyze-windows: + name: Analyze native Windows C and C++ + runs-on: windows-latest + timeout-minutes: 20 + steps: + - name: Check out source + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - category: /language:c-cpp/os:${{ matrix.os }} + persist-credentials: false + - name: Initialize CodeQL + uses: github/codeql-action/init@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3; coordinated version + with: + languages: c-cpp + build-mode: manual + - name: Build actual native and core targets + run: | + cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug + cmake --build build --parallel 2 + - name: Analyze native Windows source + uses: github/codeql-action/analyze@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3; coordinated version diff --git a/docs/reports/native-editor-2026-11-10.md b/docs/reports/native-editor-2026-11-10.md index 9fc1e77..4346f44 100644 --- a/docs/reports/native-editor-2026-11-10.md +++ b/docs/reports/native-editor-2026-11-10.md @@ -47,6 +47,14 @@ new editor-model test before running all CTests; that target is now built. These workflow integration faults, corrected without disabling tests. Corrective hosted results remain pending; Docker on the PC was not changed or used. +The corrective PR then passed all workflow jobs, but the aggregate code-scanning check was neutral: +converting the original Ubuntu analysis to explicitly categorized matrix jobs changed its required +configuration identity. Actual API records showed 58 C/C++ rules completed on both platforms, while +the original main analysis used `.github/workflows/codeql.yml:analyze` as both key/category. The +original workflow never declared Actions analysis. Its genuine Ubuntu `analyze` job is now retained +unchanged, with an independent Windows job adding real Win32 extraction. No query, supported source +scope or successful-result requirement was removed or substituted with a nominal placeholder. + Boundaries: this is an unsigned Windows portable app, not an installer, signing proof, populated-user migration or clean-machine certification. Actual own-window controls/timers were used; a human's desktop-icon click, file-dialog selection, keyboard accessibility and every OS failure condition were