Skip to content

complete layered WPF migration and retire legacy runtime#4

Open
PhantornRU wants to merge 45 commits intomainfrom
FULL_REFACTOR
Open

complete layered WPF migration and retire legacy runtime#4
PhantornRU wants to merge 45 commits intomainfrom
FULL_REFACTOR

Conversation

@PhantornRU
Copy link
Copy Markdown
Owner

@PhantornRU PhantornRU commented Apr 3, 2026

What changed

This PR completes the migration of AdaptiveSpritesDMItool from the legacy static-controller runtime to a production-grade layered WPF application.

The branch delivers:

  • a layered solution split across Domain, Application, Infrastructure, and Presentation.Wpf
  • versioned JSON config persistence with legacy CSV import as a migration-only path
  • deterministic, awaitable, cancellable batch processing with overwrite policy and per-file results
  • workspace/settings persistence and dialog-driven file/folder flows
  • a full MVVM WPF shell with empty-workspace startup, manual DMI open, config load/save/import, preview panes, batch screen, undo/redo, and interactive editor tooling
  • centralized startup/runtime hardening with logging and exception handling
  • removal of the legacy root WPF runtime, demo/test asset dependency, static controllers, legacy processors/helpers/resources, and old UI pages
  • refreshed docs and metadata aligned with the new architecture and workflow
  • warning-clean tests and ready-to-use VS Code F5 debug configuration

Why this changed

The legacy application mixed:

  • mutable global static state
  • WPF controls inside runtime state and controller dictionaries
  • CSV-centric persistence
  • startup dependency on bundled demo/test .dmi assets
  • fire-and-forget batch execution with shared counters
  • partial undo without a real session model
  • editor and file workflows inside giant code-behind files

That architecture made the app hard to test, hard to extend, and unsafe to evolve. This PR moves the runtime to explicit contracts and layered ownership so that 4-dir and 8-dir workflows, preview generation, config persistence, and batch processing are deterministic and testable.

Changelog

Foundation

  • kept the layered solution structure around src/ and tests/
  • preserved the architecture docs, ADRs, and refactor roadmap already introduced earlier in the branch

Domain + Application

  • kept the clean domain model for sprite configs, directions, metadata, validation, and empty workspace
  • extended application contracts with workspace settings, preview selection persistence, overwrite policy, and grouped editor mutations
  • completed use-case coverage for settings load/save and editor session orchestration

Infrastructure

  • added concrete IDmiWriter support via DmiSharpConfigWriter
  • added JsonWorkspaceSettingsRepository
  • tightened DMI load validation for empty inputs
  • completed end-to-end batch processing coverage with deterministic overwrite/save behavior
  • added integration tests for DMI write/apply semantics, settings persistence, and batch output reporting

WPF shell

  • rewrote the shell into a fuller MVVM workflow instead of a placeholder shell
  • added dialog-backed DMI/config/folder selection
  • added startup restore + shutdown save for workspace/settings
  • added centralized exception handling and file logging
  • wired batch execution, progress, cancellation, overwrite policy, and per-file result reporting into the UI
  • added interactive editor workflow with pointer adapter, state explorer, tool modes, direction scope, preview modes, and undo/redo integration
  • kept code-behind minimal and limited to low-level UI bridging

Legacy removal + docs

  • removed the old root project/runtime path and legacy static controllers/processors/helpers/resources/views
  • removed mandatory demo/test assets from the runtime path
  • refreshed README.md, README-ru.md, docs/CONFIG_FORMAT.md, docs/MIGRATION_GUIDE.md, and docs/TEST_PLAN.md
  • aligned documentation and package metadata with the current GPLv3 repository state and the new JSON-first workflow
  • normalized README links to repo-relative targets

Final polish

  • renamed test methods into analyzer-friendly names so the solution now builds without warnings
  • added .vscode/launch.json and .vscode/tasks.json for one-step F5 debugging of the WPF shell in VS Code

User impact

The app now starts with an empty workspace, lets users open a DMI manually, author/load/save JSON configs, import legacy CSV configs, preview base/landmark/overlay/composite states, and run deterministic batch processing without relying on legacy bundled assets or static controller state. Contributors also get a cleaner CI baseline and ready-to-use VS Code debug tasks.

Validation

Executed locally after the final polish commits:

  • dotnet build AdaptiveSpritesDMItool.sln -m:1 -v minimal
  • dotnet test AdaptiveSpritesDMItool.sln -m:1 -v minimal

Results:

  • 30 unit tests passed
  • 28 integration tests passed
  • build is warning-clean (0 warnings, 0 errors)

Commit breakdown

  1. 28bd3a6 bootstrap layered solution foundation
  2. 66d948c extract domain and application workflows
  3. b47642b add infrastructure adapters and integration tests
  4. 6c52281 build empty-workspace WPF shell
  5. fa4b754 add DMI writer and workspace settings pipeline
  6. 30ff6e5 complete MVVM shell batch and editor workflow
  7. ded383d remove legacy runtime and refresh release docs
  8. 1fef115 clean test analyzer warnings
  9. 512ae90 add VS Code debug configuration

Residual follow-up

  • optional manual exploratory UX pass in the live WPF window before marking the PR ready for review

@PhantornRU PhantornRU changed the title [codex] refactor repository into layered WPF architecture [codex] complete layered WPF migration and retire legacy runtime Apr 5, 2026
@PhantornRU PhantornRU marked this pull request as ready for review April 5, 2026 13:40
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 512ae90322

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands.cs Outdated
Comment thread src/AdaptiveSpritesDmiTool.Application/UseCases.cs Outdated
Comment thread src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Rendering.cs Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 46a9af9cb5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Surface.cs Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ebe4e14d07

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/AdaptiveSpritesDmiTool.Presentation.Wpf/App.xaml.cs Outdated
Comment thread src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands2.cs Outdated
@PhantornRU PhantornRU changed the title [codex] complete layered WPF migration and retire legacy runtime complete layered WPF migration and retire legacy runtime Apr 5, 2026
@PhantornRU
Copy link
Copy Markdown
Owner Author

Да, заюзали чтобы быстрее всё это переработать из-за нехватки времени.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a0ffd3f0b2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +93 to +94
session.LoadAsset(loadResult.Value);
workspaceService.Load(loadResult.Value);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject incompatible DMI when a config is already active

After loading a DMI, this path always updates the session asset without checking compatibility against session.CurrentConfig. If a user loads a config first and then opens a DMI with different resolution/direction depth, the workspace keeps an incompatible config in memory; subsequent preview/batch operations fail with compatibility errors and the editor surface can stay based on the stale config contract instead of the newly opened asset. LoadDmiFileUseCase should validate (or clear) the active config when the loaded asset changes.

Useful? React with 👍 / 👎.

LastLandmarkState: null,
LastOverlayState: null,
LastSelectedDirection: null,
LastOverwritePolicy: OverwritePolicy.OverwriteExisting);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Default empty workspace settings to a non-destructive policy

WorkspaceSettings.Empty initializes LastOverwritePolicy to OverwriteExisting, and LoadWorkspaceSettingsUseCase returns this value when no settings file exists. On first launch, batch mode is therefore preconfigured to overwrite outputs, which can silently replace prior exports if the user runs a batch without changing policy. This is inconsistent with other defaults in the migration (SkipExisting) and creates avoidable data-loss risk.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ac2e500ef8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +72 to +75
if (!string.IsNullOrWhiteSpace(ConfigPath) && File.Exists(ConfigPath))
{
var configResult = await _loadConfigUseCase.ExecuteAsync(ConfigPath, CancellationToken.None);
if (configResult.IsFailure)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore legacy CSV config when rebuilding startup workspace

RestoreWorkspaceAsync only reloads ConfigPath and never falls back to LegacyCsvPath, even though ApplyWorkspaceSettings and BuildWorkspaceSettings persist LastImportedLegacyCsvPath. In the common case where a user imported a legacy CSV and did not save a JSON, restarting the app drops the active config instead of restoring it, so the workspace opens without the mappings the user last used.

Useful? React with 👍 / 👎.

Сделал Stage 1 presentation-only проход поверх текущего mixed worktree.

В [MainWindow.xaml](/d:/GitHub/AdaptiveSpritesDMItool/src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml#L432) редактор переведён в matrix-first layout: direct toolbar вместо selector-heavy полосы, убран global direction selector из normal matrix flow, включён horizontal scroll для матрицы, preview уехал в collapsible inspector, нижний workspace стал visible-by-default и разложен на одновременные `States / Config / Mappings` панели вместо tab-first drawer. В том же файле я ещё уплотнил direction tiles и сделал focused mode явно experimental с быстрым `Return to Matrix`.

В [WorkspaceShellSections.cs](/d:/GitHub/AdaptiveSpritesDmiTool/src/AdaptiveSpritesDmiTool.Presentation.Wpf/WorkspaceShellSections.cs#L215) добавил только presentation glue для direct toolbar: computed selected-state flags, команды выбора tool/scope, более полезные status/lower-workspace summaries. В [MainWindowViewModel.Commands2.cs](/d:/GitHub/AdaptiveSpritesDmiTool/src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands2.cs#L337) появились минимальные команды выбора tool/scope без изменения semantics. В [MainWindowViewModel.Rendering.cs](/d:/GitHub/AdaptiveSpritesDmiTool/src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Rendering.cs#L38) lower workspace теперь раскрыт по умолчанию и workspace note приведён к parity-oriented формулировке. В [MainWindowViewModelSmokeTests.cs](/d:/GitHub/AdaptiveSpritesDmiTool/tests/AdaptiveSpritesDmiTool.Tests.Unit/Presentation/MainWindowViewModelSmokeTests.cs#L12) добавил точечные проверки на expanded lower workspace и direct toolbar selection glue.

Проверка: `git diff --check` прошёл, кроме CRLF warning-ов. Полная пересборка через `dotnet build` / `dotnet msbuild` в этом окружении по-прежнему падает на project-reference resolution без вывода реальных compile/XAML errors, поэтому compile verification неполная. `dotnet test ... --no-build` отработал на существующих binaries и дал `39 passed`, но это не заменяет свежую rebuild-проверку.

Остаточный риск: в worktree всё ещё лежат не мои mixed-scope изменения из Stage 2 / contract / settings path в [MainWindowViewModel.Commands.cs](/d:/GitHub/AdaptiveSpritesDmiTool/src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands.cs), [Contracts.cs](/d:/GitHub/AdaptiveSpritesDmiTool/src/AdaptiveSpritesDmiTool.Application/Contracts.cs), [UseCases.cs](/d:/GitHub/AdaptiveSpritesDmiTool/src/AdaptiveSpritesDmiTool.Application/UseCases.cs), [JsonWorkspaceSettingsRepository.cs](/d:/GitHub/AdaptiveSpritesDmiTool/src/AdaptiveSpritesDmiTool.Infrastructure/Settings/JsonWorkspaceSettingsRepository.cs). Их я не расширял, но перед Stage 2 branch всё ещё нужно чистить/сплитить по hunk map.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dc7235a8e2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +448 to +449
LegacyCsvPath = path;
DraftConfigName = result.Value.Name;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Clear stale save path when importing legacy CSV

After a successful legacy import, this path only updates LegacyCsvPath and leaves any existing JSON SaveConfigPath/ConfigPath intact. In the common flow where a JSON config was loaded first, SaveConfigAsync will reuse that stale save path (it only prompts when SaveConfigPath is empty), so saving the imported legacy config can silently overwrite an unrelated JSON file; resume logic also prioritizes ConfigPath over LegacyCsvPath, restoring the wrong config source.

Useful? React with 👍 / 👎.

Comment on lines +171 to +173
if (SelectedBatchSourceItem is not null &&
BatchSourceTreeItems.All(item => !string.Equals(item.FullPath, SelectedBatchSourceItem.FullPath, StringComparison.OrdinalIgnoreCase)))
{
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep nested batch selection when rebuilding source tree

This selection guard checks only the root-level BatchSourceTreeItems, but the batch picker builds nested children recursively. If a user selected a file inside a subfolder, any subsequent refresh will clear SelectedBatchSourceItem even though that file still exists, and RunBatchAsync then falls back to processing all files instead of the selected one, expanding batch scope unexpectedly.

Useful? React with 👍 / 👎.

Выполнен STAGE 1 presentation/layout revision без выхода в Stage 2 scope.

Изменения:
- В [`src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml) пересобран `Editor` layout в matrix-first схему: центральная матрица теперь доминирует, левый rail сужен, preview переведен в secondary panel, нижняя workspace area сделана always-visible вместо expander-first, toolbar уплотнен, тайлы и cell spacing уменьшены, визуальное разделение Source/Editable усилено, status bar упрощен, focused mode визуально демотирован внутри основного editor flow.
- В [`src/AdaptiveSpritesDmiTool.Presentation.Wpf/WorkspaceShellSections.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/WorkspaceShellSections.cs) упрощены summary/status-facing строки, убран shell-first/staged tone, снижен шум в lower-workspace и status-facing presentation glue.
- В [`src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs) закреплены parity-safe defaults: matrix mode как default path, нижняя workspace area visible-by-default, preview inspector недоминантен по default, стартовые workflow messages стали прямее и ближе к old editor flow.
- В [`src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands2.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands2.cs) выполнен минимальный presentation-only cleanup статусов для viewport switching и убрана лишняя привязка к expand/collapse поведениям, без изменения tool semantics.
- В [`src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Rendering.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Rendering.cs) синхронизированы reset/default/status/preview summaries под matrix-first workflow и менее staged presentation.
- В [`tests/AdaptiveSpritesDmiTool.Tests.Unit/Presentation/MainWindowViewModelSmokeTests.cs`](tests/AdaptiveSpritesDmiTool.Tests.Unit/Presentation/MainWindowViewModelSmokeTests.cs) обновлено smoke-ожидание для нового default status message.

Проверки:
- `dotnet build AdaptiveSpritesDMItool.sln` — успешно.
- `dotnet test tests/AdaptiveSpritesDmiTool.Tests.Unit/AdaptiveSpritesDmiTool.Tests.Unit.csproj --filter MainWindowViewModelSmokeTests` — 10/10 passed.

Результат ревизии направлен именно на rollback toward old matrix-first UX: 4-direction workflow больше не подан как shell-first/scroll-first, нижняя рабочая зона возвращена в основной flow, preview перестал быть dominant rail, focused mode отведен на вторичный путь, toolbar и matrix стали плотнее и прямее.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 933b7a00ae

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +284 to +286
if (string.IsNullOrWhiteSpace(SaveConfigPath) && !string.IsNullOrWhiteSpace(DmiPath))
{
SaveConfigPath = Path.ChangeExtension(DmiPath, ".json") ?? string.Empty;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Clear stale save path when creating a fresh config

CreateConfig keeps the previous SaveConfigPath unless it is blank, so a user who loaded old.json, then clicks “Create Config” and saves immediately will write the new blank config back to old.json without any prompt. This is a data-loss path because CreateConfigUseCase resets the active config to a new draft, but the persisted save target still points at the prior file.

Useful? React with 👍 / 👎.


private static IEnumerable<BatchSourceTreeItemViewModel> BuildBatchSourceTreeItems(string rootDirectory)
{
foreach (var directory in Directory.EnumerateDirectories(rootDirectory).OrderBy(static path => path, StringComparer.OrdinalIgnoreCase))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Catch access errors when enumerating batch source folders

BuildBatchSourceTreeItems recursively enumerates every child directory/file without handling UnauthorizedAccessException/IOException, so selecting or restoring an input folder that contains unreadable subfolders can throw during BatchInputDirectory updates on the UI thread and break the workspace flow. The tree builder should skip unreadable branches instead of letting enumeration exceptions escape.

Useful? React with 👍 / 👎.

Выполнен дополнительный Stage 1 correction pass.

Что исправлено:
- В [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml) центральной матрице отдано больше реальной площади: уменьшены боковые колонки, сокращена высота нижнего workspace блока, убран эффект «маленькой матрицы в большом контейнере».
- В [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml) левый rail дополнительно сужен и возвращен к роли компактного state picker без лишнего summary-блока.
- В [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml) убрано дублирование states между левым rail и нижней зоной: states оставлены слева, нижняя зона сфокусирована на config + mappings.
- В [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml) preview дополнительно демотирован: панель уже, текстового шума меньше, визуальный приоритет снижен.
- В [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml) `Focused` убран из primary toolbar flow и переведен во вторичный affordance рядом со status/hint line.
- В [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml) matrix block больше не завязан на `Viewbox`-центрирование для normal matrix mode, поэтому он заполняет доступную editor area заметно агрессивнее.

Что осталось в scope и не менялось:
- Без правок [`MainWindow.xaml.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml.cs), [`MainWindowViewModel.Commands.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands.cs), [`MainWindowViewModel.Surface.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Surface.cs).
- Без изменений application contracts, use-cases, preview builder и interaction semantics.
- Без изменений Settings tab.

Проверки:
- `dotnet build AdaptiveSpritesDMItool.sln` — успешно.
- `dotnet test tests/AdaptiveSpritesDmiTool.Tests.Unit/AdaptiveSpritesDmiTool.Tests.Unit.csproj --filter MainWindowViewModelSmokeTests` — успешно, 10/10 passed.

Измененные файлы в этом correction pass:
- [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml)
- ранее подготовленные presentation-support изменения в [`WorkspaceShellSections.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/WorkspaceShellSections.cs), [`MainWindowViewModel.State.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs), [`MainWindowViewModel.Commands2.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands2.cs), [`MainWindowViewModel.Rendering.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Rendering.cs), [`MainWindowViewModelSmokeTests.cs`](tests/AdaptiveSpritesDmiTool.Tests.Unit/Presentation/MainWindowViewModelSmokeTests.cs).

Итог: layout сдвинут еще ближе к old matrix-first UX — матрица крупнее, боковые и нижние зоны слабее давят на editor, preview и focused mode стали более вторичными, а экран распределяет место в пользу основной 4-direction рабочей области.
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

1. Что изменено по layout
- В [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml) editor workspace перестроен из статического `states | source | editable | directions` в адаптивную композицию: optional single-state strip, optional horizontal directions strip, adaptive central workspace и скрытый по умолчанию bottom dock.
- Editable viewport теперь всегда является главным визуальным хостом: в default-сценарии отдельная source-колонка не занимает ширину, а compare/overlay режимы включаются явно.
- Для compare режима добавлен resizable split между reference/source и editable в [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml).
- Для 4-dir сценария directions перенесены в компактную горизонтальную полосу, для 8-dir+ сохранен правый vertical rail в [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml).

2. Какие новые VM flags / enum / commands добавлены
- Добавлен enum [`EditorViewMode`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:9) с режимами [`EditableOnly`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:11), [`CompareSplit`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:12) и [`OverlayCompare`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:13).
- Добавлены presentation flags [`IsEditableOnlyMode`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:266), [`IsCompareSplitMode`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:268), [`IsOverlayCompareMode`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:270), [`IsReferencePaneVisible`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:272), [`ShowOverlayCompareLayer`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:274), [`ShowStatesRail`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:282), [`ShowSingleStateStrip`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:284), [`UseHorizontalDirectionsStrip`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:286), [`UseVerticalDirectionsRail`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:288), [`HasDirectionSelector`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:290), [`CanFitViewport`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:298) и состояние [`isFocusMode`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:210).
- Добавлены команды [`SetEditableOnlyMode()`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands2.cs:392), [`SetCompareSplitMode()`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands2.cs:395), [`SetOverlayCompareMode()`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands2.cs:398), [`ToggleFocusMode()`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands2.cs:401) и [`FitViewport()`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands2.cs:415).

3. Какие файлы затронуты
- [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml)
- [`MainWindowViewModel.State.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs)
- [`MainWindowViewModel.Rendering.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Rendering.cs)
- [`MainWindowViewModel.Commands.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands.cs)
- [`MainWindowViewModel.Commands2.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands2.cs)
- [`MainWindowViewModel.Surface.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Surface.cs)
- [`WorkspaceShellSections.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/WorkspaceShellSections.cs)

4. Как теперь работает default editor mode
- Default editor mode теперь идет через [`EditorViewMode`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:154) со стартовым значением [`EditableOnly`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:11).
- После открытия DMI/конфига adaptive layout не показывает source pane постоянно; editable viewport сразу получает основную рабочую ширину.
- Bottom dock остается скрытым по умолчанию, как и после первого этапа reset.

5. Как работает compare/overlay/focus
- Compare mode включает отдельный source pane через [`IsReferencePaneVisible`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:272) и `GridSplitter` в [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml); editable остается шире source и split не 50/50.
- Overlay mode не создает отдельную source-колонку, а рендерит presentation-only source overlay поверх editable host в [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml), не ломая существующий surface pipeline.
- Focus mode переключается через [`ToggleFocusMode()`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands2.cs:401): скрывает states rail, directions selector, reference pane и принудительно оставляет bottom dock закрытым.

6. Как работает adaptive directions layout
- Для 4 направлений включается [`UseHorizontalDirectionsStrip`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:286), и directions отображаются горизонтальной selector-strip над viewport в [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml).
- Для наборов больше 4 включается [`UseVerticalDirectionsRail`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:288), и справа показывается vertical rail.
- Для 0/1 направления selector вообще не расходует место через [`HasDirectionSelector`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:290).

7. Как работает single-state compaction
- Полноценный left states rail теперь зависит от [`ShowStatesRail`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:282), то есть показывается только при multi-state workflow.
- При single-state сценарии включается [`ShowSingleStateStrip`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:284), и вместо целой колонки рендерится компактная strip-row с текущим state и действиями Base/Landmark/Overlay/Clear в [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml).

8. Как реализован adaptive zoom / fit
- Fit command идет через [`FitViewport()`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands2.cs:415), а доступность определяется флагом [`CanFitViewport`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:298).
- Adaptive zoom bootstrap встроен в [`MainWindowViewModel.Rendering.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Rendering.cs) и вызывается после инициализации workspace, открытия DMI, загрузки JSON-конфига и импорта legacy CSV через [`MainWindowViewModel.Commands.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands.cs).
- Эвристика основана на resolution: small sprites получают повышенный стартовый zoom, поэтому 32x32 больше не выглядит потерянным как на условных 100%.
- Существующая zoom-модель не сломана: колесо мыши и [`ResetEditorZoom()`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Commands2.cs:422) продолжают работать поверх новой bootstrap-логики.

9. Результат сборки
- Сборка [`AdaptiveSpritesDMItool.sln`](AdaptiveSpritesDMItool.sln) прошла успешно: `0 Warning(s), 0 Error(s)`.

10. Какие осознанные компромиссы остались
- Overlay compare реализован как presentation-only visual overlay в [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml), а не как глубокий merge в render pipeline; это сохраняет behavior compatibility и не трогает domain/application/infrastructure.
- Adaptive fit пока использует resolution-driven heuristic из [`MainWindowViewModel.Rendering.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.Rendering.cs), а не live viewport measurement по фактическому размеру host-контейнера.
- Focus mode не сворачивает глобальный shell/navigation rail, чтобы не влезать глубже в navigation architecture; он ограничен editor-level compaction, чего достаточно для acceptance criteria второго этапа.
1. Audit summary
- Убраны широкие верхние блоки из [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml): отдельная status-row, отдельная `State` row и full-width directions strip больше не являются default presentation path.
- Из top area в left rail перенесены:
  - вертикальный список states,
  - selector `Base / Landmark / Overlay / Clear`,
  - medium `Source` pane,
  - selector directions.
- Вниз, в secondary/status bar, перенесены:
  - active direction,
  - hover/selection summary,
  - sprite/config metadata,
  - `Composite`,
  - `Refresh`,
  - `Auto`,
  - zoom label,
  - reset zoom,
  - bottom dock toggle.
- Новый layout ближе к legacy workflow, потому что теперь editor читается как:
  - сверху действия,
  - слева контекст редактирования,
  - по центру рабочее полотно,
  - снизу служебная строка.
  Это возвращает editable canvas в роль главного элемента окна.

2. Список измененных файлов с пояснением
- [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml) — полностью пересобрана композиция `Editor` tab, новые sidebar/status templates и toolbar styles.
- [`MainWindowViewModel.State.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs) — добавлены/уточнены layout flags для нового контракта editor shell.
- [`WorkspaceShellSections.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/WorkspaceShellSections.cs) — проброшены новые presentation properties в editor-facing VM, добавлены compact labels для directions и state count.

3. Реализация
- Верх editor-а ужат до одной primary toolbar row в [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml).
- Введены новые стили:
  - [`EditorPrimaryToolbarButtonStyle`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml),
  - [`EditorPrimaryToolbarToggleStyle`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml),
  - [`EditorPrimaryToolbarCheckBoxStyle`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml),
  - [`SidebarSectionBorderStyle`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml),
  - [`StateListItemStyle`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml),
  - [`SidebarDirectionListBoxItemStyle`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml).
- Добавлены templates:
  - [`StateSidebarItemTemplate`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml),
  - [`SidebarDirectionItemTemplate`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml).
- Добавлены explicit layout flags в [`MainWindowViewModel.State.cs`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs):
  - [`ShowEditorLeftRail`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:283),
  - [`ShowStateLayersPanel`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:285),
  - [`ShowSourcePalettePane`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:287),
  - [`ShowDirectionsInSidebar`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:289),
  - [`ShowBottomStatusBar`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:291),
  - [`ShowCompactCanvasHeader`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindowViewModel.State.cs:293).
- Эти flags проброшены в [`EditorWorkspaceViewModel`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/WorkspaceShellSections.cs:437).

4. Как теперь устроен left rail
- Left rail теперь единый вертикальный sidebar фиксированной ширины в [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml).
- Внутри него идут секции:
  - `States`,
  - `Target layer`,
  - `Source`,
  - `Directions`.
- `States` показываются как вертикальный scrollable layers-like list, а не как горизонтальная полоса.
- В заголовке states показывается summary через [`StateCountLabel`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/WorkspaceShellSections.cs:530).

5. Где теперь живет source/original pane
- `Source/Original` теперь постоянно живет в left rail в виде medium preview-pane в [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml).
- Это read-only/working reference для обычного `Edit` режима.
- В `CompareSplit` дополнительно появляется отдельный compare-source surface в центральной области, то есть compare расширяет информацию, а не подменяет архитектуру sidebar.

6. Где теперь живет target layer selector
- `Base / Landmark / Overlay / Clear` теперь находятся в секции `Target layer` внутри left rail в [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml).
- Они больше не занимают отдельную широкую row над canvas.

7. Где теперь живут directions
- Directions переехали в секцию `Directions` внутри left rail в [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml).
- Используется компактный grid-паттерн через [`SidebarDirectionItemTemplate`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml) и [`SidebarDirectionListBoxItemStyle`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml).
- Для short labels добавлено свойство [`ShortLabel`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/WorkspaceShellSections.cs:437) в item VM.
- Full-width horizontal strip над canvas больше не является основным presentation path.

8. Что осталось в top toolbar
- Вверху остались только primary editing controls:
  - tools,
  - scope,
  - view mode,
  - `Undo`,
  - `Redo`,
  - `Clear`,
  - `Fit`,
  - `Focus`.
- Controls стали текстовыми/labeled, а не набором неочевидных анонимных glyph-кнопок.
- Это реализовано в верхнем toolbar block в [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml).

9. Что уехало в bottom status bar
- В нижнюю secondary/status bar editor-а переехали:
  - active direction,
  - hover/status summary,
  - sprite metadata,
  - config metadata,
  - preview mode combo,
  - `Refresh`,
  - `Auto`,
  - `Grid`,
  - `Overlay`,
  - zoom label,
  - `100%`,
  - `Bottom dock`.
- Это собрано в bottom editor status bar внутри [`MainWindow.xaml`](src/AdaptiveSpritesDmiTool.Presentation.Wpf/MainWindow.xaml).

10. Manual verification checklist
- single-state
  - states больше не раздуваются в wide horizontal strip
  - left rail остается компактным и читаемым
- multi-state
  - states отображаются как вертикальный список
  - selection видна явно
- 4-dir
  - directions живут в sidebar, не во full-width strip
- 8-dir
  - directions продолжают работать через sidebar grid
- Edit
  - left rail visible
  - medium source pane visible
  - editable canvas доминирует
- Compare
  - left rail сохраняется
  - compare добавляет central reference pane
  - `GridSplitter` работает
- Overlay
  - left rail сохраняется
  - source overlay остается поверх editable
- Focus
  - left rail скрывается
  - bottom secondary bar скрывается
  - остается компактный toolbar + canvas
- state selection
  - list selection остается рабочим через существующий binding
- target layer selection
  - `Base/Landmark/Overlay/Clear` работают из sidebar
- source/original visibility
  - source pane всегда виден в обычном `Edit`
- status readability
  - статус/мета собраны внизу в одну строку
- top toolbar compactness
  - больше нет 3–4 stacked rows над canvas
- canvas vertical space increase
  - центральная рабочая область получила больше высоты, чем в предыдущем состоянии

11. Результат сборки
- [`dotnet build AdaptiveSpritesDMItool.sln`](AdaptiveSpritesDMItool.sln) проходит успешно: `0 Warning(s), 0 Error(s)`.
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fba8f00d34

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (_host is not null)
{
var viewModel = _host.Services.GetService<MainWindowViewModel>();
viewModel?.PersistWorkspaceSettingsAsync().GetAwaiter().GetResult();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Replace blocking shutdown settings flush

OnExit blocks the dispatcher with PersistWorkspaceSettingsAsync().GetAwaiter().GetResult(), but settings persistence is also triggered in fire-and-forget calls and waits on _workspaceSettingsPersistenceGate before saving. Because that wait captures the UI context, a pending persistence continuation can require the dispatcher to run in order to release the semaphore; blocking the dispatcher here can deadlock app shutdown and leave the window hanging during exit.

Useful? React with 👍 / 👎.

OverlayStateName = settings.LastOverlayState ?? string.Empty;
SelectedDirection = settings.LastSelectedDirection ?? SelectedDirection;
SelectedOverwritePolicy = settings.LastOverwritePolicy;
SelectedEditorViewportMode = EditorViewportMode.Matrix;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore saved viewport mode from workspace settings

BuildWorkspaceSettings persists SelectedEditorViewportMode, but startup restore hard-codes SelectedEditorViewportMode = EditorViewportMode.Matrix instead of reading settings.LastEditorViewportMode. This means users always lose their last chosen viewport mode (e.g., Focused) after restart even though it is written to disk.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f559c773cd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +119 to +122
if (!Enum.TryParse<OverwritePolicy>(value, true, out var policy))
{
throw new JsonException($"Unsupported overwrite policy '{value}'.");
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject undefined overwrite policy values from settings

ParseOverwritePolicy accepts numeric strings because Enum.TryParse is used without checking Enum.IsDefined. A malformed settings file value like "99" is therefore treated as a valid enum and loaded into SelectedOverwritePolicy; later batch processing falls through the switch default path and behaves like overwrite mode, which can replace existing outputs unexpectedly. Validate that parsed enum values are defined members before accepting them.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5aec5350ad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +443 to +447
ConfigPath = string.Empty;
SaveConfigPath = string.Empty;
DraftConfigName = "Unsaved Draft";
StatusMessage = "Removed the active config.";
RefreshWorkspaceState();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reset session config when removing final queue item

When the active queue item is removed and no DMI is loaded, this branch only clears ConfigPath/SaveConfigPath UI fields but leaves _editorSession.CurrentConfig intact. RefreshWorkspaceState() then calls RefreshConfigQueueItems(), and UpsertCurrentSessionIntoConfigQueue() re-creates a queue item from the still-active session config, so the removal effectively does not stick in config-only workflows. Clear the session config (or reset the session) before refreshing state.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 18d555d3e2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}

[RelayCommand]
private void SetEditableOnlyMode() => SetEditorViewMode(EditorViewMode.CompareSplit, "Dual workspace active.");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Switch editable-only command to EditableOnly mode

SetEditableOnlyMode currently passes EditorViewMode.CompareSplit, so triggering the "Editable only" action can never activate EditorViewMode.EditableOnly. In practice the UI stays in dual-pane mode and IsEditableOnlyMode-dependent bindings never become true, which breaks the mode switch behavior users expect.

Useful? React with 👍 / 👎.


SelectedDirectionScope = scope;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clear origin mappings when moving editable selections

The move workflow only applies mappings to translated coordinates and does not remove mappings from the original coordinates, so dragging a mapped pixel/area effectively copies it instead of moving it. This leaves stale mappings behind in the source area whenever the destination differs from the origin, contradicting the "Move" tool semantics.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant