- NEVER commit OR push without explicit user permission
- Ask clarifying questions BEFORE making a plan
- ALWAYS make a plan before starting work, and wait for explicit user confirmation
main— latest released versiondevelop— next version in progress; feature branches merge here
- Solution file:
src/CovertActionTools.sln - Build:
dotnet buildordotnet publishfromsrc/ - Core targets netstandard2.0 — do not use C# features unavailable in netstandard2.0 when editing Core
- App targets net8.0
- Tests:
dotnet testfromsrc/runs all test projects (xUnit, target net8.0) - Two test projects:
CovertActionTools.UnitTests.Core(isolated unit tests with mocks) andCovertActionTools.IntegrationTests.Core(real dependencies, roundtrip and snapshot tests)
- Two projects:
CovertActionTools.Core(library, all data/parsing logic, no GUI dependency) andCovertActionTools.App(ImGui + Veldrid desktop GUI, depends on Core) - Data pipeline pattern: Legacy binary files →
LegacyParser→Importer(JSON package) →Exporter(JSON) →Publisher(legacy binary). Each data type (Crime, Animation, Text, Image, etc.) has one of each - All Core services are registered in
Core/ServiceCollectionExtension.cs. All App ViewModels/Windows are auto-discovered inApp/Program.cs. New importers/exporters/publishers must be added toServiceCollectionExtension - Every model implements
Clone()— when adding new fields to a model, always add them toClone()too
- VGA 16-color palette is defined in
Core/Constants.cs. Color indices 13 (player clothing) and 14 (enemy clothing) are special — replaced dynamically by the game engine at draw time - Many models contain
Unknown*fields (e.g.Unknown1,Unknown2). These are partially reverse-engineered from the binary format. Do not rename, remove, or repurpose them
- Organise tests by domain area in folders (e.g.
Compression/,Parsers/), with each area having its own test data generator helper - Each test data generator should be named for its area (e.g.
LzwTestDataGenerator,SharedImageTestDataGenerator) — no genericTestDataGenerator - Test data generators, snapshot data, and snapshot generators live in a
Data/subfolder within each area (e.g.Parsers/Data/,Compression/Data/) - Test stubs and mocks live in a
Stubs/subfolder within each area (e.g.Parsers/Stubs/) - Unit tests (
UnitTests.Core): mock dependencies (e.g.ILzwDecompression), use hand-crafted byte arrays for inputs, test the class in isolation - Integration tests (
IntegrationTests.Core): use real dependencies, no mocks. Two styles:- Roundtrip: use the Exporter to generate binary data, then parse it back with the Parser and verify the output matches the original input
- Snapshot: capture known-good outputs as base64 constants in a helper class, assert against them for regression detection
- Both test projects access Core internals via
InternalsVisibleTo— keep Core .csproj updated when adding new test projects
- Keep all temporary and transient files (e.g. TASKS.md, investigation notes, scratch scripts) in the
scratch/subfolder at the repo root - The
scratch/folder is gitignored (except.gitkeep) — nothing in it will be committed
- Prefer making classes
internalunless they are consumed outside Core. Test projects get access viaInternalsVisibleTo - Use
#region Name/#endregionto group related code sections — not// --- Name ---comments - Do not use
<Using>in .csproj files — addusingdirectives explicitly in each source file