Skip to content

Complete layered WPF migration and retire legacy runtime#4

Merged
PhantornRU merged 58 commits into
mainfrom
FULL_REFACTOR
May 15, 2026
Merged

Complete layered WPF migration and retire legacy runtime#4
PhantornRU merged 58 commits into
mainfrom
FULL_REFACTOR

Conversation

@PhantornRU

@PhantornRU PhantornRU commented Apr 3, 2026

Copy link
Copy Markdown
Owner

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

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

Copy link
Copy Markdown

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

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

Copy link
Copy Markdown

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

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

Copy link
Copy Markdown

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

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

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

Copy link
Copy Markdown

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 👍 / 👎.

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

Copy link
Copy Markdown

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.

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

Copy link
Copy Markdown

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 стали плотнее и прямее.

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

Copy link
Copy Markdown

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.

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

Copy link
Copy Markdown

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.

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

Copy link
Copy Markdown

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: 4b91921366

ℹ️ 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".


private static OverwritePolicy ParseOverwritePolicy(string? value)
{
if (!Enum.TryParse<OverwritePolicy>(value, true, out var policy))

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 Validate manifest overwrite policy enum values

ParseOverwritePolicy accepts numeric strings like "99" because Enum.TryParse succeeds for undefined underlying values; those values then flow into batch execution, where DeterministicBatchProcessingService.EvaluateOverwritePolicy falls through its switch default and behaves like overwrite mode. In a malformed or manually edited manifest, this can silently overwrite existing outputs instead of failing validation, which is a data-loss risk.

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.

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

Copy link
Copy Markdown

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: f59186ce6b

ℹ️ 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 +326 to +329
private static string NormalizeOutputSubdirectory(string value) =>
string.IsNullOrWhiteSpace(value) || value == "."
? string.Empty
: value.Trim().Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);

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 Canonicalize output subdirectory before duplicate detection

The duplicate-job guard can be bypassed by equivalent path spellings (for example "sprites" vs "sprites/" or "./sprites") because NormalizeOutputSubdirectory only trims whitespace and separator style, then compares raw strings. Later ResolveManifestJobOutputDirectory resolves both to the same physical directory, so two enabled jobs can silently share one output folder and overwrite each other’s files/artifacts. Normalize to a canonical relative path (or compare resolved full paths) before inserting into outputSubdirectories.

Useful? React with 👍 / 👎.

Comment on lines +1010 to +1013
private static BottomWorkspaceTab ParseBottomWorkspaceTab(string? value) =>
Enum.TryParse<BottomWorkspaceTab>(value, true, out var tab)
? tab
: BottomWorkspaceTab.Mappings;

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 enum values when restoring bottom tab

Enum.TryParse accepts numeric strings, so a malformed settings value like "99" is treated as a valid BottomWorkspaceTab here. That propagates an out-of-range SelectedBottomWorkspaceTabIndex, and the same invalid value is then persisted again on save, leaving the bottom workspace tab state broken across restarts. This parser should mirror ParseEditorViewportMode by rejecting numeric/undefined enum values and falling back to a safe default.

Useful? React with 👍 / 👎.

@PhantornRU PhantornRU changed the title complete layered WPF migration and retire legacy runtime Complete layered WPF migration and retire legacy runtime May 13, 2026

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

Copy link
Copy Markdown

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: 38fad4db56

ℹ️ 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 +442 to +444
plan.Config,
plan.OverwritePolicy,
pendingFiles),

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 Force overwrite for stale files in incremental batch runs

When ExecuteJobAsync decides a file is stale (journal mismatch) it still forwards the job’s original overwrite policy to batchProcessingService. In BatchRunMode.Incremental, this breaks updates whenever the policy is SkipExisting or FailIfExists: stale files are re-queued but then skipped/failed because their old output already exists, so the output never gets refreshed and the journal entry never advances. This causes incremental runs to repeatedly keep outdated artifacts instead of recomputing changed inputs.

Useful? React with 👍 / 👎.

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

Copy link
Copy Markdown

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: 6e9fda3cdc

ℹ️ 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 +154 to +156
var explicitFiles = SelectedBatchSourceItem is { IsDirectory: false, FullPath: not null }
? new[] { SelectedBatchSourceItem.FullPath }
: null;

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 Respect selected folder when running batch

The batch runner only builds explicitFiles when the selected source tree item is a file, so selecting a directory silently falls back to null and processes the entire BatchInputDirectory. In practice, users who pick a subfolder in the batch tree will unintentionally run against all inputs (and potentially overwrite outputs outside the intended subset), which is a scope-expansion bug rather than a UI-only issue.

Useful? React with 👍 / 👎.

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

Copy link
Copy Markdown

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: 7259cdcc25

ℹ️ 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".

RefreshConfigQueueItems();
RefreshSampleConfigItems();
RefreshEditorAssetItems();
RefreshBatchPipelineState();

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 Avoid rescanning batch sources during every workspace refresh

RefreshWorkspaceState() is invoked after routine editor mutations, and this unconditional call to RefreshBatchPipelineState() forces the batch tree to be rebuilt (and validation restarted) even when only pixel mappings changed. With a large BatchInputDirectory, each edit/undo can trigger recursive filesystem work and repeated DMI inspections, causing avoidable UI slowdowns in normal editing flows. The batch source pipeline should refresh only when batch-related inputs change (e.g., input path, selected source, or loaded asset), not on every workspace repaint.

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.

@PhantornRU PhantornRU merged commit 2900206 into main May 15, 2026
2 checks passed
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