Skip to content
This repository was archived by the owner on Oct 22, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
15 changes: 10 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ jobs:
run: dotnet --info

- name: Restore dependencies
run: dotnet restore ${{ env.SOLUTION_PATH }} --runtime ${{ env.RUNTIME_IDENTIFIER }} -p:PublishAot=true
run: dotnet restore ${{ env.SOLUTION_PATH }} --runtime ${{ env.RUNTIME_IDENTIFIER }}

- name: Run tests
run: dotnet test ${{ env.SOLUTION_PATH }} --configuration Release --no-restore

- name: Verify NativeAOT publish
- name: Verify publish
shell: pwsh
run: |
dotnet publish $env:PROJECT_PATH `
Expand All @@ -51,9 +51,14 @@ jobs:
--self-contained true `
--no-restore `
--output artifacts/ci-publish `
-p:JsonSerializerIsReflectionEnabledByDefault=false `
-p:WarningsAsErrors=IL2026%3BIL3050 `
-p:PublishAot=true `
-p:PublishSingleFile=true `
-p:IncludeNativeLibrariesForSelfExtract=true `
-p:DebugType=none `
-p:DebugSymbols=false

- name: Upload CI build artifact
uses: actions/upload-artifact@v7
with:
name: ci-build-${{ github.run_number }}
path: artifacts/ci-publish
if-no-files-found: error
2 changes: 1 addition & 1 deletion .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ on:
workflow_dispatch:

concurrency:
group: pages-${{ github.event.pull_request.number || github.ref }}
group: pages-${{ github.event_name == 'pull_request' && github.event.pull_request.number || 'deployment' }}
cancel-in-progress: false

jobs:
Expand Down
34 changes: 0 additions & 34 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,44 +93,12 @@ jobs:
"executable_path=$executablePath" >> $env:GITHUB_OUTPUT

- name: Generate checksum
id: checksum
shell: pwsh
run: |
$executablePath = "${{ steps.executable.outputs.executable_path }}"
$hash = (Get-FileHash -Path $executablePath -Algorithm SHA256).Hash.ToLowerInvariant()
$checksumFile = "artifacts/SHA256"
"$hash $(Split-Path $executablePath -Leaf)" | Set-Content -Path $checksumFile -Encoding utf8
"sha256=$hash" >> $env:GITHUB_OUTPUT
"checksum_path=$checksumFile" >> $env:GITHUB_OUTPUT

- name: Generate update manifest
shell: pwsh
run: |
$tag = "$env:TAG_NAME"
$executableFilename = "${{ steps.release.outputs.artifact_name }}.exe"
$sha256 = "${{ steps.checksum.outputs.sha256 }}"
$repositoryUrl = "https://github.com/${{ github.repository }}"
$manifestPath = "artifacts/update.json"

$manifest = [ordered]@{
schemaVersion = 1
version = $tag
releaseUrl = "$repositoryUrl/releases/tag/$tag"
downloadUrl = "$repositoryUrl/releases/download/$tag/$executableFilename"
sha256 = $sha256
}

$manifest | ConvertTo-Json | Set-Content -Path $manifestPath -Encoding utf8

$parsed = Get-Content -Raw -Path $manifestPath | ConvertFrom-Json

if ($parsed.schemaVersion -ne 1 -or
$parsed.version -ne $tag -or
$parsed.downloadUrl -notlike "*/$executableFilename" -or
$parsed.sha256 -ne $sha256 -or
$parsed.sha256 -notmatch '^[0-9a-f]{64}$') {
throw "Generated update manifest failed validation."
}

- name: Prepare release notes
id: notes
Expand Down Expand Up @@ -204,7 +172,6 @@ jobs:
path: |
artifacts/${{ steps.release.outputs.artifact_name }}.exe
artifacts/SHA256
artifacts/update.json
artifacts/release-notes.md
if-no-files-found: error

Expand Down Expand Up @@ -232,4 +199,3 @@ jobs:
files: |
artifacts/${{ needs.build.outputs.executable_filename }}
artifacts/SHA256
artifacts/update.json
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ x86/
bld/
[Bb]in/
[Oo]bj/
/localization/*.Designer.cs
[Ll]og/
[Ll]ogs/

Expand All @@ -43,6 +44,7 @@ ScaffoldingReadMe.txt
~$*
*~
CodeCoverage/
*.DotSettings.user

# MSBuild Binary and Structured Log
*.binlog
Expand All @@ -60,5 +62,6 @@ nunit-*.xml
.idea/

# Agent tool files
.agents/
.codex/
.claude/
51 changes: 25 additions & 26 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# AGENTS.md

UnityAssetsPatcher is a .NET 10 console app for inspecting Unity assets files and installing or uninstalling mods.

It provides a Terminal.Gui-based interactive UI and a non-interactive CLI.
UnityAssetsPatcher is a .NET 10 and Avalonia desktop application for managing Unity assets mods.

## Commands

Expand All @@ -11,35 +9,36 @@ It provides a Terminal.Gui-based interactive UI and a non-interactive CLI.
| Build | `dotnet build UnityAssetsPatcher.slnx` |
| Test | `dotnet test UnityAssetsPatcher.slnx` |

Existing tests may be updated to reflect authorized implementation changes. Do not add test files or test cases unless the user explicitly requests them.

## Repository Structure

| Directory | Responsibility |
| :------------------------------------------------------ | :--------------------------------------------------------------------------------------------------- |
| `src/UnityAssetsPatcher/` | Executable entry point and composition root; owns dependency registration and concrete logging setup |
| `src/UnityAssetsPatcher.Application/` | Use cases, workflow orchestration, DTOs, and infrastructure abstractions |
| `src/UnityAssetsPatcher.CLI/` | Non-interactive command parsing and text/JSON presentation |
| `src/UnityAssetsPatcher.Domain/` | Domain models, value objects, validation rules, and domain errors |
| `src/UnityAssetsPatcher.Infrastructure/` | File system, compression, persistence, backup, package, and AssetsTools.NET implementations |
| `src/UnityAssetsPatcher.LocalizationGenerator/` | Roslyn source generator for strongly typed localized strings |
| `src/UnityAssetsPatcher.TUI/` | Interactive terminal UI and localization inputs |
| Directory | Responsibility |
| :--------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------- |
| `docs/` | User and mod author documentation |
| `schema/` | Mod manifest schema |
| `src/UnityAssetsPatcher/` | Executable entry point, dependency composition, concrete logging setup, and Avalonia UI; owns presentation, localization, and user interaction |
| `src/UnityAssetsPatcher.Application/` | Use cases, business workflow orchestration, transaction and recovery policies, DTOs, and infrastructure interfaces |
| `src/UnityAssetsPatcher.Domain/` | Business models, value objects, validation rules, and domain errors independent of infrastructure |
| `src/UnityAssetsPatcher.Infrastructure/` | File system, compression, persistence, package parsing, and external integrations implementing Application interfaces |
| `tests/` | Unit and integration tests |

## Architecture

## Project Architecture
### Application Configuration

[ARCHITECTURE.md](./ARCHITECTURE.md)
- `AppConfig` is the static source for application identity, version, and fixed application directories.
- `AppRuntimeConfig` is the singleton source for mutable process-level settings such as verbose logging.

## Workflows
### Application Boundaries

### 1. Implementing a Feature
- Prefer direct, use-case-oriented application APIs.
- Return business data directly by default. Use use-case-specific results when callers need to distinguish multiple normal business outcomes; allow null or empty collections when their meaning is unambiguous. Do not require a common result wrapper.
- Infrastructure propagates original platform and third-party exceptions without wrapping, translating, or replacing them. Application interprets known failures according to the use-case contract and may expose specific application exceptions. UI owns their presentation.

1. Read the user's requirements and inspect the relevant existing code, configuration, content, and documentation.
2. Before editing implementation files, present a concrete plan that describes the intended behavior, affected areas, and validation steps.
3. Do not modify source code or other implementation files, and do not run commands that rewrite or generate files, until the user explicitly approves the plan and authorizes implementation. Read-only inspection is allowed.
4. After approval, implement only the approved scope. If a materially different approach or broader scope becomes necessary, explain the change and request approval again before proceeding.
5. Validate the implementation with the commands required by this document and report the result.
### Exception Policy

### 2. Fixing a Bug
- `Program.Main` is the single process-level unexpected-exception boundary, covering startup, dependency composition, GUI execution, and asynchronous disposal. It logs full diagnostics once, shows generic output without internal details, and terminates with a non-zero exit code.
- Boundary logging must outlive the dependency container. Unexpected failures from UI and background work must reach this boundary promptly, rather than waiting for disposal; lower layers must not log or convert them into expected failures.
- Only the creator of a `CancellationTokenSource`, or the lifecycle boundary explicitly given control of it, may consume cancellation after verifying a cancellation request and matching exception token identity. Integrations that cannot preserve identity require a narrowly scoped, documented adapter. An unmatched cancellation escaping to `Program.Main` is treated as unexpected.

1. Start from the user's problem description. Inspect the relevant code and, when practical, reproduce the issue using read-only or non-mutating diagnostics.
2. Identify the root cause and support the diagnosis with concrete evidence from the code or reproduction. Do not present an unverified guess as the cause.
3. Explain the root cause, affected behavior, proposed fix, and validation plan to the user. Wait for explicit approval before modifying source code or other implementation files.
4. After approval, implement the fix within the agreed scope, add or update regression coverage when appropriate, and run the required validation commands.
Loading
Loading