Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/workflows/dotnet-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ jobs:
- name: Test
run: dotnet test ChapterTool.Avalonia.slnx --configuration Release --no-build --blame-hang --blame-hang-timeout 10m --blame-hang-dump-type full

- name: Validate PowerShell publish script
shell: pwsh
run: |
$null = [System.Management.Automation.Language.Parser]::ParseFile(
(Join-Path $PWD 'scripts/publish.ps1'),
[ref]$null,
[ref]$null)

- name: Pack ChapterTool.Core
run: dotnet pack src/ChapterTool.Core/ChapterTool.Core.csproj --configuration Release --no-restore --output artifacts/nuget

Expand Down Expand Up @@ -76,6 +84,9 @@ jobs:
- name: Publish
run: ./scripts/publish.sh -Runtime ${{ matrix.runtime }} -NoRestore -PublishSingleFile

- name: Verify publish artifact
run: ./scripts/verify-publish-artifact.sh -Runtime ${{ matrix.runtime }} -Path artifacts/publish/framework-dependent/${{ matrix.runtime }}

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
Expand Down
49 changes: 30 additions & 19 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# AGENTS.md

## Dev Environment Tips
## Repository Overview

- This repo contains the legacy WinForms project under `Time_Shift/` and the current .NET 10 Avalonia/Core/Infrastructure solution under `src/`.
- Use `ChapterTool.Avalonia.slnx` for the current Avalonia/Core/Infrastructure solution.
- This repo is the current .NET 10 ChapterTool codebase. Use `ChapterTool.Avalonia.slnx` as the main solution.
- Main projects:
- `src/ChapterTool.Core`
- `src/ChapterTool.Infrastructure`
Expand All @@ -12,12 +11,21 @@
- `tests/ChapterTool.Infrastructure.Tests`
- `tests/ChapterTool.Avalonia.Tests`
- Prefer `rg` for searching files and text.
- When reading files with PowerShell, explicitly use UTF-8, for example:
- `Get-Content -Raw -Encoding utf8 path\to\file`
- `[System.IO.File]::ReadAllText($path, [System.Text.Encoding]::UTF8)`
- Keep this file focused on durable repository guidance. Do not add one-off implementation notes, completed change records, or transient archive paths here.
- Do not port WinForms absolute positioning into Avalonia. Use responsive Avalonia layout panels and stable sizing constraints.
- Use `docs/code-map/` as the primary navigation index for the current codebase. Update the relevant files there when feature work changes module ownership, entry points, runtime wiring, or the main tests a maintainer should inspect.
- Keep user-facing Chinese strings as valid UTF-8. Validate localization through behavior, rendered UI, or resource-level checks rather than hard-coding incidental mojibake examples.
- CLI argument entry points must be defined, parsed, and bound through `DotMake.CommandLine`; do not hand-write logic in `Program.cs` or CLI support code to iterate, recognize, or dispatch raw `args`.
- Keep this file focused on durable repository guidance. Do not add one-off implementation notes, completed change records, or transient archive paths here.

## PowerShell Guidance

- On Windows, prefer `pwsh.exe` over `powershell.exe` unless Windows PowerShell 5.1 is explicitly required.
- For short native-command invocations, pass the executable and arguments separately. Store the executable path in a variable, keep each native argument as one array item, invoke with `&`, and capture `$LASTEXITCODE` immediately.
- For cmdlets and file operations, prefer PowerShell-native commands with splatting and `-LiteralPath` when working with real paths.
- For file operations, prefer explicit path and encoding handling. Use `-LiteralPath` for real paths, specify UTF-8 when reading or writing text, and avoid relying on implicit wildcard expansion or default encodings.
- `Get-Content -Raw -Encoding utf8 -LiteralPath $path`
- `[System.IO.File]::ReadAllText($path, [System.Text.Encoding]::UTF8)`
- For multiline scripts, complex quoting, JSON, XML, regular expressions, or non-ASCII paths, write a temporary `.ps1` file and run it with `pwsh.exe -NoLogo -NoProfile -NonInteractive -File script.ps1`.
- Do not use `Invoke-Expression` for normal task execution.

## OpenSpec Workflow

Expand All @@ -31,27 +39,30 @@
- After completing and archiving a change, validate all specs:
- `openspec validate --all`

## Testing Instructions
## Testing And Build

- Run the focused Avalonia tests after XAML or UI shell changes:
- `dotnet test tests\ChapterTool.Avalonia.Tests\ChapterTool.Avalonia.Tests.csproj --no-restore`
- Keep Avalonia Headless tests isolated without serializing the entire Avalonia test assembly. Do not reintroduce assembly-level `CollectionBehavior(DisableTestParallelization = true)` for this project; instead put every class containing `[AvaloniaFact]` or `[AvaloniaTheory]` in `AvaloniaHeadlessTestCollection`. The guard test `HeadlessTestCollectionGuardTests` exists to catch missed classes.
- When a test constructs `SettingsToolViewModel` and then calls `LoadAsync` explicitly, pass `autoLoad: false`. Otherwise the constructor starts a background load and the test performs the same initialization twice, which slows Headless runs and can introduce races.
- Do not test source/configuration files by reading them as text and asserting strings. This includes `.cs`, `.axaml`, `.csproj`, scripts, CI YAML, README, and docs. Prefer compiled coverage, behavior tests, runtime verification, structured public APIs, or integration checks.
- Run the full solution tests before finalizing broader changes:
- `dotnet test ChapterTool.Avalonia.slnx --no-restore`
- Do not run multiple `dotnet test` commands for projects in this solution in parallel. The test projects share referenced project `obj/` outputs, and parallel external test processes can fail with locked files such as `src/ChapterTool.Core/obj/Debug/net10.0/ChapterTool.Core.dll`. Prefer the full solution test command above, or run individual test projects sequentially.
- Build the Avalonia app when changing app project files:
- `dotnet build src\ChapterTool.Avalonia\ChapterTool.Avalonia.csproj --no-restore`
- If dependencies, target frameworks, or generated project assets change, restore/build once before running no-restore test commands.
- The CI workflow is in `.github/workflows/dotnet-ci.yml`.
- If a test/build fails because `ChapterTool.Avalonia.exe` is locked, close the running app or run:
- `Get-Process ChapterTool.Avalonia -ErrorAction SilentlyContinue | Stop-Process`
- Do not run multiple `dotnet test` commands for projects in this solution in parallel. The test projects share referenced project `obj/` outputs, and parallel external test processes can fail with locked files such as `src/ChapterTool.Core/obj/Debug/net10.0/ChapterTool.Core.dll`. Prefer the full solution test command above, or run individual test projects sequentially.
- Keep Avalonia Headless tests isolated without serializing the entire Avalonia test assembly. Do not reintroduce assembly-level `CollectionBehavior(DisableTestParallelization = true)` for this project; instead put every class containing `[AvaloniaFact]` or `[AvaloniaTheory]` in `AvaloniaHeadlessTestCollection`. The guard test `HeadlessTestCollectionGuardTests` exists to catch missed classes.
- Keep Avalonia Headless tests focused on UI behavior and workflow outcomes. Prefer tests that drive user actions or state changes and then verify the resulting UI state, command routing, localization refresh, selection changes, or persisted behavior.
- Do not add Headless tests that only assert a control exists, a static label renders, a window opens, a screenshot file was written, or a layout has non-zero size unless that assertion is part of a broader user-facing behavior change being verified.
- When a test constructs `SettingsToolViewModel` and then calls `LoadAsync` explicitly, pass `autoLoad: false`. Otherwise the constructor starts a background load and the test performs the same initialization twice, which slows Headless runs and can introduce races.
- Do not test source/configuration files by reading them as text and asserting strings. This includes `.cs`, `.axaml`, `.csproj`, scripts, CI YAML, README, and docs. Prefer compiled coverage, behavior tests, runtime verification, structured public APIs, or integration checks.
- Add or update tests for changed behavior, especially UI layout constraints, UTF-8 labels, import/export behavior, and platform-service boundaries.
- If dependencies, target frameworks, or generated project assets change, restore/build once before running no-restore test commands.

## UI Implementation Notes
## Avalonia UI Guidelines

- The Avalonia main window should preserve workflow zones, not WinForms pixel geometry:
- Use responsive Avalonia layout panels and stable sizing constraints. Do not rely on absolute positioning for normal workflow controls.
- The Avalonia main window should preserve these workflow zones:
- top load/save and frame controls
- central chapter grid
- bottom options area
Expand All @@ -62,13 +73,13 @@
- Keep DataGrid columns protected with sensible `MinWidth` values so headers and content do not overlap when resized.
- Buttons should center content horizontally and vertically.
- Do not expose Windows registry-dependent actions, such as file association, as always-visible primary UI.
- When verifying visual layout changes, capture screenshots at default, wide, and narrow sizes and store them under `artifacts/`.
- Avoid static string assertions over source/configuration layout. Validate UI through Avalonia compilation, behavior-level tests, and screenshots/runtime checks instead.
- When verifying visual layout changes manually, capture screenshots at default, wide, and narrow sizes and store them under `artifacts/`. Do not treat screenshot generation by itself as an automated test assertion.
- Preserve accessible names, keyboard navigation, focus behavior, and localization boundaries when changing controls.

## PR Instructions
## Change And PR Expectations

- Keep changes scoped to the current feature or fix.
- Mention the primary test commands run in the PR or final summary.
- For UI changes, include screenshot artifact paths when available.
- When a feature change affects code ownership or lookup paths, update the relevant files under `docs/code-map/` in the same change.
- Do not revert unrelated user or generated changes in a dirty worktree.
12 changes: 12 additions & 0 deletions dist/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Distribution

ChapterTool's maintained distribution path is the .NET 10 Avalonia publish flow:

- `scripts/publish.sh`
- `scripts/publish.ps1`
- `.github/workflows/dotnet-ci.yml`

The legacy Windows NSIS installer inputs were retired because they targeted the old
`Time_Shift`/`ChapterTool.exe` layout and carried an independent hard-coded version.
Any future installer must consume the current `src/ChapterTool.Avalonia` publish
output and derive metadata from the MSBuild version source in `Directory.Build.props`.
Loading
Loading