diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..bd67d49 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,56 @@ +# GitHub Copilot Repository Instructions: C++23 Modernization + +## Context +- Language: C++ +- Target standard: C++23 +- Goal: modernize legacy C++11/14/17 code safely and incrementally + +## Primary Rule +Preserve existing behavior unless functional changes are explicitly requested. + +## Balanced Modernization Policy +- Prefer modern C++23 constructs when they clearly improve safety, readability, or maintainability. +- Keep refactors focused and reviewable; avoid broad rewrites unless requested. +- Prefer standard library solutions over custom or legacy patterns. +- Respect toolchain limitations, ABI-sensitive interfaces, and repository-local style. + +## Preferred Modernizations +- Use `auto` where the type is obvious from the initializer; avoid it when it hides important type information. +- Prefer structured bindings over `std::tie` or manual pair/tuple access when clearer. +- Replace raw owning pointers and manual `delete` with RAII, usually `std::unique_ptr`. +- Use `std::make_unique` and `std::make_shared`; prefer `std::shared_ptr` only for real shared ownership. +- Use `std::string_view` for read-only string parameters only when lifetime safety is clear. +- Prefer `std::span` for non-owning contiguous ranges. +- Use `std::mdspan` only when multidimensional access is central and the change improves clarity or safety. +- Prefer `.contains()` over `find(...) != end()` where available and clearer. +- Prefer standard algorithms and ranges over manual loops when readability improves. +- Use `[[nodiscard]]` where ignoring the result is likely a bug. +- Prefer early returns over deeply nested control flow. +- Use `std::optional` monadic operations (`and_then`, `transform`, `or_else`) when they make the code simpler. +- Prefer `constexpr`, `if constexpr`, concepts, and `requires` over legacy `std::enable_if` / SFINAE where practical. +- Add `noexcept`, `override`, `final`, `= default`, and `= delete` where correct and useful. +- Prefer `enum class` over unscoped enums where practical. +- Prefer `std::print` / `std::println` for console output when supported by the project toolchain. +- Prefer typed `std::chrono` durations and `std::jthread` where appropriate. + +## Avoid +- Do not modernize mechanically if readability becomes worse. +- Do not introduce unsupported C++23 features. +- Do not introduce dangling references, dangling `std::string_view`, or unclear ownership. +- Do not silently change ABI, object lifetime, exception behavior, or performance characteristics. +- Do not rewrite unrelated code. + +## Expected Copilot Behavior +When making migration suggestions: +- produce small, focused updates +- explain non-trivial changes briefly +- call out risky refactors explicitly +- note compatibility or toolchain caveats +- leave optional follow-up improvements separate + +## Preferred Output +Provide: +- updated code +- short rationale +- compatibility/toolchain caveats +- optional next modernization steps diff --git a/scripts/combined-migration-compact.prompt b/scripts/combined-migration-compact.prompt new file mode 100644 index 0000000..031c9ff --- /dev/null +++ b/scripts/combined-migration-compact.prompt @@ -0,0 +1,157 @@ +# GitHub Copilot Instructions: Qt5/C++11 to Qt6/C++23 Migration + +## Mission +Migrate the legacy Qt5/C++11 desktop application to Qt6/C++23, preserve behavior unless change is strictly required, and validate the result completely in the repository’s Docker-based CI workflow. + +## Operating Mode +- Work autonomously from analysis through validation. +- Do not stop after editing code. +- Continue until configure, build, tests, and policy checks have been attempted in Docker. +- Do not ask for confirmation during normal implementation. +- Stop early only if required source material is missing, the task is impossible, or a destructive action would be required. + +## Boundaries +- Read the legacy project from `${PROJECT_DIR}`. +- Write the migrated project to `qt6-after/qt6-migrated-benchmark`. +- Do not modify the legacy source tree in place. +- Limit changes to the target tree and only the CI/build/test files needed to support migration and validation. + +## Main Migration Targets +- Upgrade Qt5 to Qt6. +- Upgrade C++11/14/17 code to C++23. +- Keep Qt Core, Gui, and Widgets explicitly linked. +- Replace `QRegExp` with `QRegularExpression`. +- Replace `QDesktopWidget` and `QApplication::desktop()` with `QScreen`-based Qt6 APIs. +- Remove legacy `QTextCodec` usage and adopt Qt6-safe text handling. +- Replace old `SIGNAL`/`SLOT` syntax with function-pointer connect syntax. +- Replace `0`/`NULL` pointer literals with `nullptr`. +- Preserve `.ui` and `.qrc` integration. +- Preserve behavior unless Qt6 compatibility requires adaptation. + +## C++23 Modernization Rules +- Preserve semantics first; modernize second. +- Use `auto` when the type is obvious; avoid it when it hides important type information. +- Prefer structured bindings where clearer. +- Replace raw owning pointers/manual `delete` with RAII, usually `std::unique_ptr`. +- Use `std::make_unique` / `std::make_shared`; use `std::shared_ptr` only for real shared ownership. +- Use `std::string_view` only when lifetime safety is clear. +- Prefer `std::span` for non-owning contiguous data; use `std::mdspan` only when multidimensional access clearly benefits. +- Prefer `.contains()` over `find(...) != end()` where available. +- Prefer algorithms and ranges over manual loops when readability improves. +- Use `[[nodiscard]]` when ignoring a result is likely a bug. +- Prefer early returns over deeply nested control flow. +- Use `std::optional` monadic operations (`and_then`, `transform`, `or_else`) when clearer. +- Prefer `constexpr`, `if constexpr`, concepts, and `requires` over legacy `std::enable_if`/SFINAE where practical. +- Add `noexcept`, `override`, `final`, `= default`, and `= delete` where correct and useful. +- Prefer `enum class` over unscoped enums where practical. +- Prefer `std::print` / `std::println` when supported by the toolchain. +- Prefer typed `std::chrono` durations and `std::jthread` where appropriate. + +## Safety Rules +- Do not change business logic unless explicitly requested or required for Qt6 compatibility. +- Do not introduce unsupported Qt6/C++23 features. +- Do not silently change ABI, ownership, lifetime, exception behavior, performance, UI behavior, or event ordering. +- Do not worsen readability for the sake of modernization. +- Avoid dangling references, dangling `std::string_view`, and ownership ambiguity. +- Keep includes minimal and preserve repository-local formatting/style. + +## Tests +- For every code change inside a method, add at least three tests covering the changed behavior. +- Place generated tests in `qt6-after/qt6-migrated-benchmark/tests`. +- Use policy-compatible test filenames such as: + - `test_.cpp` + - `_test.cpp` + - `test.cpp` + - `gtest.cpp` +- Update CMake so the migrated app and all tests build and run with CTest. +- Ensure all tests are registered with CTest. + +## Docker-First Validation +Use `lifemaps/ci-cpp:latest` as the authoritative environment. Do not substitute host tools for missing container tools. Treat `Dockerfile.ci` as the source of truth for CI dependencies. + +### Required validation sequence +1. Configure in Docker +2. Build in Docker +3. Run tests in Docker +4. If tests pass, run `python3 ci/check_pr_policies.py` in Docker + +### Recommended commands +- Configure: + `cmake -S qt6-after/qt6-migrated-benchmark -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug` +- Build: + `cmake --build build --parallel` +- Test: + `ctest --test-dir build --output-on-failure` +- Policy: + `python3 ci/check_pr_policies.py` + +Adapt paths/flags only if repository inspection proves they must differ. + +## Missing-Tool Remediation +If Docker validation fails because a required tool/package is missing: +- identify the exact missing dependency +- update `Dockerfile.ci` minimally +- rebuild `lifemaps/ci-cpp:latest` +- rerun the full validation sequence + +Continue until: +- validation succeeds, or +- the next blocker is a genuine project/code issue + +## Failure Classification +Environment failures: +- command not found +- missing compiler/toolchain utility +- missing Qt dev package +- missing CMake/Ninja/CTest support tool +- missing dependency required by `ci/check_pr_policies.py` + +Project failures: +- compile errors +- linker errors +- failing tests +- formatting/policy failures caused by migration changes + +## Policy Awareness +- `ci/check_pr_policies.py` checks formatting for changed C/C++ files, expects related tests, and verifies commit-signature conditions in its diff range. +- Ensure Docker validation runs with mounted workspace and git metadata available. +- Do not claim success unless the policy script passes. + +## Execution Plan +1. Inspect `${PROJECT_DIR}` and the target tree. +2. Identify Qt5 and legacy C++ constructs to migrate. +3. Migrate incrementally in `qt6-after/qt6-migrated-benchmark`. +4. Add/update tests with each behavior-relevant change. +5. Update CMake/test registration. +6. Validate in Docker. +7. If missing dependencies are found, update `Dockerfile.ci`, rebuild, and rerun. +8. Repeat until success or a real project defect remains. + +## Reporting +Group change explanations by: +- CMake / build-system migration +- Qt API replacements +- C++ modernization +- UI/resource preservation +- tests added +- `Dockerfile.ci` / container updates + +Also provide a concise changed-files summary. + +## Completion Criteria +Success requires: +- migrated project exists under `qt6-after/qt6-migrated-benchmark` +- configure succeeds in Docker +- build succeeds in Docker +- tests succeed in Docker +- `python3 ci/check_pr_policies.py` succeeds in Docker after tests pass + +## Final Response +- State whether migration is fully validated or which blocker remains. +- List the exact Docker commands used for image rebuild, configure, build, test, and policy check. +- For every failed attempt, include: + - exact command + - key error + - environment vs project classification + - fix applied +- End with a short summary of any remaining blocker. \ No newline at end of file diff --git a/scripts/migration-cpp23.prompt b/scripts/migration-cpp23.prompt new file mode 100644 index 0000000..051d94a --- /dev/null +++ b/scripts/migration-cpp23.prompt @@ -0,0 +1,119 @@ +# GitHub Copilot Repository Instructions: C++ Modernization + +## Project Context +- **Language:** C++ +- **Target Standard:** C++23 (Strict enforcement) +- **Migration Goal:** Systematically upgrade legacy C++11/C++14/C++17 code to modern C++23 paradigms. + +## Core Objective +Modernize the codebase incrementally and safely. Preserve existing behavior unless the task explicitly requests functional changes. Prefer small, reviewable refactors that improve correctness, safety, readability, and maintainability. + +## Global Migration Principles +- Preserve semantics first; modernize second. +- Prefer standard C++23 library facilities over custom utilities where equivalent. +- Favor compile-time validation, explicit ownership, and strong type safety. +- Reduce boilerplate only when readability improves. +- Avoid unnecessary churn in code that is already modern and clear. +- Keep ABI-sensitive or externally exposed interfaces stable unless breaking changes are explicitly allowed. +- For larger migrations, refactor file-by-file or subsystem-by-subsystem. + +## Migration Rules + +### 1. Type Inference & Variables +- Replace explicit types with `auto` where the type is obvious from the initializer. +- Do not use `auto` when it obscures important type information or changes value/reference semantics unintentionally. +- Prefer `const auto` and `const auto&` where appropriate. +- Use structured bindings (`auto [x, y] = ...`) instead of `std::tie`, `.first/.second`, or tuple indexing where it improves clarity. +- Prefer uniform initialization where appropriate. + +### 2. Memory & Resource Management +- Replace raw owning pointers and manual `delete` with `std::unique_ptr` or `std::shared_ptr`. +- Prefer `std::unique_ptr` by default; use `std::shared_ptr` only for true shared ownership. +- Use `std::make_unique` and `std::make_shared`. +- Enforce RAII for all resource management. +- Replace manual lifetime management with scoped objects where possible. +- Distinguish clearly between owning and non-owning access; prefer references, `std::span`, or observer-style usage for non-owning views. + +### 3. Containers, Views & Strings +- Use `std::string_view` for read-only string parameters where lifetime safety is guaranteed. +- Never introduce dangling `std::string_view`. +- Replace `if (items.find(key) != items.end())` with `if (items.contains(key))` where supported. +- Prefer `.starts_with()`, `.ends_with()`, and `.contains()` when they improve readability. +- Prefer `std::span` for non-owning contiguous views. +- Use `std::mdspan` for multidimensional indexing only where it meaningfully improves safety or clarity. +- Prefer standard algorithms and ranges over manual loops when they improve readability and maintainability. +- Avoid unnecessary copies; prefer move semantics, `emplace`, and views where safe. + +### 4. Control Flow & Error Handling +- Prefer early returns over deep nesting. +- Use `[[nodiscard]]` for functions whose return values should not be ignored. +- Modernize `std::optional` usage with `.and_then()`, `.transform()`, and `.or_else()` where this makes the logic clearer. +- Replace sentinel values with `std::optional`, strong types, or `std::expected` if supported by the project/toolchain. +- Preserve existing exception guarantees and error behavior unless changes are explicitly requested. + +### 5. Formatting & Output +- Replace `printf` and legacy `` console output with `` where toolchain support exists. +- Use `std::print` and `std::println` for standard console output. +- If `` is unavailable in the project toolchain, note the limitation and prefer the most modern supported alternative. +- Do not mix output styles in the same updated code path without a strong reason. + +### 6. Compile-Time Optimization & Templates +- Maximize appropriate use of `constexpr`. +- Use `consteval` and `constinit` where semantically beneficial. +- Replace legacy SFINAE / `std::enable_if` with Concepts and `requires` clauses. +- Use `if constexpr` to simplify compile-time branching. +- Prefer readable template constraints and diagnostics over complex metaprogramming. + +### 7. API & Interface Modernization +- Add `noexcept` where correct and useful. +- Use `override` consistently for overridden virtual functions. +- Use `final` where appropriate. +- Prefer `= default` and `= delete` for special member functions. +- Prefer `enum class` over unscoped enums where practical. +- Replace output parameters with return values or small result structs where this improves clarity and does not break required interfaces. + +### 8. Concurrency & Time +- Prefer modern standard library concurrency primitives. +- Use `std::jthread` instead of `std::thread` where automatic joining and cancellation semantics are beneficial. +- Prefer typed `std::chrono` durations and literals over raw integer time values. + +## Code Style Enforcement +- Avoid C-style macros where `constexpr`, `const`, enums, or inline functions are better. +- Never introduce deprecated or removed standard library facilities. +- Prefer expressive, self-documenting code over mechanical modernization. +- Keep includes minimal and correct. +- Avoid hidden lifetime bugs, dangling references, dangling views, and ownership ambiguity. +- Preserve repository formatting and local style conventions unless explicitly changing them. + +## Safety Constraints +- Do not change business logic unless explicitly requested. +- Do not silently alter ownership semantics without calling it out. +- Do not replace code with newer constructs if the result is harder to read. +- Do not introduce C++23 features that are unsupported by the project compiler/toolchain. +- Highlight any modernization that may affect ABI, performance, exception behavior, or object lifetime. + +## Review Checklist +For each proposed migration, verify: +- Behavior is preserved. +- Ownership and lifetime are clearer and safer. +- Readability is improved. +- Interface compatibility is maintained unless breaking changes are allowed. +- C++23 features are applied only where beneficial. +- Toolchain compatibility is respected. +- Tests and warnings should still pass after the change. + +## Expected Copilot Behavior +When modernizing code: +1. Start from the existing implementation and refactor incrementally. +2. Prefer minimal, reviewable patches over broad rewrites. +3. Briefly explain non-trivial modernizations. +4. Call out risky or behavior-adjacent changes explicitly. +5. Provide optional follow-up refactors separately when they are useful but non-essential. +6. Avoid touching unrelated code. + +## Preferred Output Format +For each migration task, provide: +- the modernized code, +- a short rationale, +- any compatibility/toolchain caveats, +- and optional next-step improvements.tes