Build strict NUnit parity harness
Some checks failed
Rust API gates / api-gates (push) Has been cancelled

This commit is contained in:
2026-08-08 16:47:41 +02:00
parent c8a953996e
commit 80fbe87b98
10 changed files with 19784 additions and 17083 deletions

View File

@@ -36,9 +36,11 @@ Generated inventories are intentionally checked in:
Run `python3 tools/generate_surface.py` after deliberately changing the pinned
upstream snapshot, then run `python3 tools/extract_public_api.py` to rebuild the
authoritative metadata catalog twice and require byte-identical output. The
source generator rejects a test count other than 1,295 so upstream drift cannot
source generator rejects a test count other than 1,289 so upstream drift cannot
silently remove tests. Update both commit constants and review all ledger diffs
in the same change.
in the same change. The earlier 1,295 inventory included five commented-out
`[Test]` attributes and double-counted the parameterless `[Test]` marker on one
parameterized `[TestCase]` method; those are not NUnit invocations.
### Current shell status
@@ -57,8 +59,8 @@ The current workspace is a structural baseline, not a working client:
slices expose all 3,066 final Rust-facing types and all 30,789 callable
members with real fields/constants/enum values and standardized failing
bodies;
- all 1,295 NUnit `[Test]`/`[TestCase]` invocations have compiling Rust test
entries that intentionally panic with their source identity and body hash;
- all 1,289 real NUnit `[Test]`/`[TestCase]` invocations have stable catalog
entries; pending cases do not generate executable placeholder tests;
- all nine sample/tool projects have compiling Rust binary targets;
- the 128 TestClient command source files are retained as a command inventory.
@@ -66,8 +68,8 @@ No generated type shells remain pending: all cataloged members are callable,
and the standalone downstream fixture names or invokes all 3,066 types and
30,789 members with zero exclusions. `api/SURFACE.tsv` is still an inventory
aid, not proof of API coverage: it records declaration lines but does not fully
parse multiline signatures. Likewise, a generated `pending` test is a parity
placeholder, not a semantic translation. **The full public API signature shim
parse multiline signatures. Likewise, a pending catalog entry is not a
semantic translation. **The full public API signature shim
gate is complete; semantic test translation is the next stage.**
The avatar-facing slice preserves the C# agent, movement/camera, appearance and
@@ -316,12 +318,21 @@ The signature gate is complete only when:
### 3.2 Full semantic test-suite gate
After the full signature shim compiles, translate the entire C# test suite while
leaving all library bodies unimplemented. Every one of the 1,295 NUnit
leaving all library bodies unimplemented. Every one of the 1,289 NUnit
invocations must become a Rust test with the same inputs, setup, operation,
observations, assertions, tolerances and expected error/event behavior. Shared
C# test helpers become shared Rust test helpers; embedded fixtures and literal
payloads are copied with license/source attribution and byte hashes.
The parity harness is in place: every invocation has a stable source/case ID,
parameter identity, body hash, category, fixture dependency list, Rust location,
and semantic-review status. Reviewed tests are identified by `parity-case`
markers in hand-written Rust files, so regeneration records unresolved cases
without creating fake executable tests and fails on body drift. The checked-in
audit reports pending, translated, ignored-live, benchmark, drifted, missing,
duplicate, stale, and unreviewed cases; the initial handover contains 1,289
unreviewed cases.
The Rust tests must call the public APIs rather than internal replacements.
Where the C# tests call internal members through friend-assembly access, record
that fact and place equivalent Rust unit tests inside the owning crate without
@@ -336,7 +347,7 @@ they must distinguish the intended invariant from the placeholder panic.
The test-suite gate is complete only when:
- `pending(` occurs zero times in Rust test sources;
- no generated placeholder or dispatcher body can count as reviewed;
- the parity catalog reports exactly one reviewed Rust case for every upstream
`[Test]`/`[TestCase]`, with the matching C# body hash;
- `cargo test --workspace --no-run` compiles all tests against public signatures;
@@ -669,14 +680,14 @@ the complete signature gate in section 3.1 across all crates. Then translate the
complete suite in section 3.2 across all crates. Only after both global gates
may implementation proceed in dependency order.
For each generated test:
For each pending catalog case:
1. Open the exact C# source/line and verify its method-body SHA-256 still matches
`tests/upstream-tests.json`.
2. Identify setup, action, assertions, parameterized cases, fixtures, categories,
and intended exception/event/timeout behavior.
3. Replace only that Rust `pending(...)` body with semantically equivalent Rust.
Keep the generated Rust test name or update the ledger in the same change.
3. Write an explicit Rust `#[test]` body in a hand-written test file, add its
`parity-case` marker, and call the mapped library API directly.
4. Port literal bytes, UUIDs, timestamps, tolerances, culture assumptions, and
ordering exactly. Do not weaken an assertion merely because the shim differs.
5. If the needed API is absent, stop and treat that as a signature-coverage
@@ -717,8 +728,8 @@ cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo doc --workspace --no-deps
```
During Stage 0, `cargo test --workspace` fails in generated parity placeholders.
During the full test-suite gate, `pending(` is the explicit remaining-work
During Stage 0, pending cases exist only in the parity catalog. During the full
test-suite gate, the catalog's pending count is the explicit remaining-work
count and CI prohibits increases. At the end of that gate, tests still fail,
but only because callable production signatures report standardized
not-implemented member IDs. During implementation, that failure inventory then
@@ -774,7 +785,7 @@ not part of the default smoke test.
map 100% of public members to reviewed Rust signatures, and implement only
standardized failing bodies. All signatures and downstream compile fixtures
build before test translation begins.
3. **Full semantic test translation:** replace all 1,295 `pending` cases with
3. **Full semantic test translation:** replace all 1,289 pending cases with
exact reviewed Rust equivalents using the public shim. The entire suite
compiles and fails only at standardized unimplemented member boundaries.
4. **Types implementation:** UUID, math, enums, conversions, collections,