# Agent guidelines These rules apply throughout this repository. Keep purpose, status, usage, and development instructions in `README.md`; keep agent workflow rules here. Neither file is a session log. ## Scope and repository map This is a WIP .NET double-double arithmetic library, not arbitrary-precision math. Do not claim API completeness or accuracy beyond tested contracts. - `0-source/Just.PreciseMath/`: library implementation and package metadata. - `1-tests/Just.PreciseMath.Tests/`: xUnit v3 tests, Shouldly assertions, and Microsoft.Testing.Platform (MTP) with `coverlet.MTP` coverage. - `2-benchmarks/Just.PreciseMath.Benchmarks/`: source-free BenchmarkDotNet library scaffold, not yet a runnable benchmark suite. - Root `Directory.Build.props` holds shared settings. Each numbered directory's props explicitly imports it; preserve this import chain. - `review-legacy/`: optional local reference material, excluded by `.gitignore`. Start with `review-legacy/Review-Revisited-DoubleDouble.md` when present. The code and proposed fixes contain known defects: reproduce findings against current code rather than treating them as correctness oracles. Do not compile, copy wholesale, or force-add these files. If absent, proceed without them; do not invent their contents or make validation depend on them. - Use the ignored, repository-local `.hermes/` directory for plans, checklists, investigation notes, and handoff context. Create or update notes as useful; keep them concise and revalidate them against current files. Optional `.hermes/project-context.md` holds setup and review background. Do not store secrets, force-add this directory, or make builds or tests depend on it. ## Working rules - Check both staged and unstaged changes before starting. Preserve the user's work and index; do not stage, commit, push, publish packages, or rewrite history without an explicit request. Do not read or expose credentials. - Read definitions, callers, tests, and relevant configuration before editing. Limit changes to the request; do not implement the roadmap or repair unrelated WIP code. - Reproduce numerical bugs with a failing regression test before fixing them. For new behavior, define the contract and test cases before implementation. Exercise sibling overloads and operand orders that can share the defect. - Do not weaken analyzers, nullable checks, warnings-as-errors, or assertions to get a green build. Explain necessary policy changes before making them. - Keep dependencies minimal. Check existing references, compatibility, and current stable releases before adding or upgrading packages. ## C# conventions Follow `.editorconfig`, not incidental style in unfinished code. - Use file-scoped namespaces, explicit types rather than `var`, and block-bodied methods. Preserve the configured expression-bodied property/accessor preferences. - Use `_camelCase` for non-public instance fields, including internal fields; `s_camelCase` for non-public mutable static fields; PascalCase for constants and static readonly fields. Do not rename internal fields to remove underscores. - Preserve parentheses that make mathematical grouping readable. `IDE0047` is intentionally disabled; do not re-enable it or remove grouping as style cleanup. - Document public APIs and non-obvious numerical preconditions. Explain algorithms, error behavior, and range constraints rather than narrating syntax. - Tests and benchmarks already have internal access through `InternalsVisibleTo`; do not widen the public API merely to make a helper testable. ## Numerical correctness - Treat floating-point evaluation order as part of the algorithm. Do not reassociate expressions, discard residuals, replace fused multiply-add with multiply-plus-add, or simplify error-free transforms without justification and regression tests. Mathematically equivalent formulas can round differently. - State and verify algorithm preconditions, especially magnitude ordering for quick-sum transforms, normalization assumptions, and overflow/underflow limits. - The internal two-component `DoubleDouble` constructor currently does not normalize. Do not assume arbitrary pairs are canonical. Establish the intended normalization, NaN, infinity, and signed-zero contracts before changing construction, equality, hashing, ordering, or classification; keep those operations consistent. - For affected operations, cover cancellation, widely separated magnitudes, zero and signed zero, subnormals, extreme finite values, infinities, and NaNs. Check intermediate overflow/underflow even when the final result is representable. - Derive expected values from independent high-precision references or exact binary/rational cases, never from the implementation under test. Record the reference source or reproducible derivation and justify tolerances. - Do not collapse both components to `double` or `decimal` to validate double-double accuracy: that can discard precisely the bits being tested. Use component-aware or higher-precision comparisons, and inspect sign bits when testing signed zero. - Smoke tests, coverage percentages, and benchmark output are not proof of numerical correctness. ## Build and verification Run commands from the repository root. Read SDK and runner selection from `global.json`; read framework, language, and dependency versions from project and props files rather than duplicating version pins here. For documentation-only changes, validate referenced paths and any new or changed commands, then run `git diff --check`. Report commands actually run, their outcomes, and anything not verified. Distinguish pre-existing failures from failures introduced by the change. ### Code or build changes Use targeted tests while iterating, then run the full sequence: ```sh dotnet restore Just.PreciseMath.slnx --locked-mode dotnet build Just.PreciseMath.slnx -c Release --no-restore dotnet test --solution Just.PreciseMath.slnx -c Release --no-build --minimum-expected-tests 1 dotnet format Just.PreciseMath.slnx --verify-no-changes --no-restore git diff --check ``` Use verify-only formatting first. Report unrelated existing violations separately and validate the changed files; do not reformat the repository to hide failures. ### Test or coverage pipeline changes After the code/build checks, also run: ```sh dotnet test --solution Just.PreciseMath.slnx -c Release --no-build --minimum-expected-tests 1 --report-xunit-trx --coverlet --coverlet-output-format cobertura --coverlet-include "[Just.PreciseMath]*" ``` Keep MTP-native options and the empty-suite failure. Do not substitute VSTest collector commands or remove compile assets from `coverlet.MTP`; generated MTP registration requires them. Inspect actual TRX and Cobertura output, including failed-test behavior when changing report collection. ### Packaging changes After the code/build checks, run: ```sh dotnet pack 0-source/Just.PreciseMath/Just.PreciseMath.csproj -c Release --no-build ``` Inspect package metadata and the included `README.md` and `LICENSE`. Do not publish. ### Dependency changes For intentional dependency changes, run `dotnet restore --force-evaluate` and review all affected `packages.lock.json` files before the locked restore above. Include lock-file updates in the change; never regenerate them to bypass unexpected restore failures. ## CI and benchmarks - `.gitea/workflows/test-dotnet.yaml` is the CI source of truth. Keep reports artifact-only: no badges, publication branches, or repository-write publishing jobs. - Preserve upload-on-failure and both report globs: `1-tests/**/TestResults/**/*.trx` and `1-tests/**/TestResults/**/*cobertura*.xml`. Cobertura filenames can be timestamped; `*.cobertura.xml` alone will miss them. - Cache NuGet packages, not `bin/` or `obj/`; restore remains necessary on a cache hit. A local restore does not prove CI cache reuse or remote artifact upload succeeded. - Before upgrading actions, check each action's required Node runtime against both the Gitea runner and job image. A recent runner can still launch an old Node image; `ubuntu-latest` is a configured label, not a guarantee of GitHub's environment. - Do not add an empty benchmark job. When benchmarks are introduced, add an executable entry point and cases, then smoke-run them in Release with BenchmarkDotNet's Dry job. Require discovered/executed cases and verify that benchmark failures fail CI. - Keep smoke validation separate from performance measurement. Do not gate timing regressions on a shared runner or compare coverage-instrumented measurements. Use controlled, repeatable baseline/candidate runs before proposing performance gates.