Skip to content

Restore the seven Nauvis tier-2 guards behind a predicate-counting export (#227) #367

Description

@wormeyman

Tier 2 lost seven Nauvis anti-vacuity guards when #227 deleted the TypeScript arm. Each one counted per-point hits over the swept grid, and checksum_nauvis returns an order-sensitive fold, which cannot be decomposed back into counts. An engine export that answers a predicate over the sweep would restore all seven.

What went, and what each one was holding up

All seven lived in test/wasmNauvisParity.spec.ts and were deleted in the #227 source-deletion PR. Their frozen numbers are recorded here so a restoration re-measures them rather than re-deriving them - and so a number that comes back different is a finding rather than a surprise.

guard frozen value what it caught
the tile field names match the catalog's own order 21 tiles; FIELD_NAMES[16] = tile:deepwater, [36] = tile:red-desert-3, [37] = resolvedTileIndex a catalog reordering relabelling every downstream failure instead of failing here
the tree field names match the catalog's own order 15 species; block base 57, base + 18 = treeDensity, base + 19 = cliffElevation same, for TREE_SPECIES
the enemy sweep reaches spots rather than folding the basement per case [331, 412, 484, 401, 393, 0]; 160 positions with a positive enemy probability a window that reached no enemy cone would fold the -1000 basement at every position and compare nothing
the cliff gate answers both ways and the rock density is not vacuous 327 positions where cliffiness is 10; 72 with a non-zero rock density cliffiness is 0 or 10 and nothing else, so a window that answered one way everywhere would fold a constant
the tree density is not vacuous over the swept windows 927 positions with a non-zero tree density a sweep with no forest in it folds zeros on both sides - agreement about nothing
the resolved tile index really is an index into the catalog integral, 0 <= v < 21, more than one distinct value in case 0 resolvedTileIndex crosses the ABI as an f64, so a wrong widening still folds to some number
every resource is actually drawn somewhere in the sweep [7, 3, 5, 4, 4, 1] positions per resource across the six cases a probability field folds 484 zeros where its resource is absent; a sweep with no ore in it grades nothing

The 84-field x 6-case frozen fold itself is intact, as is "the cases actually differ from each other, field by field" (already read from the engine), the f32-grid coverage guard (it reads coordinates, not fields), and the two block-position guards (they read FIELD_NAMES literals).

Why the fold cannot stand in

Every one of these asks "how many swept positions satisfy P", and the export gives back one FNV fold of every value in sweep order. Two different hit counts can produce any pair of folds, so the count is not recoverable. Three of them - the enemy per-case array, the cliff gate, the resource drawn array - are exactly the "silent loss of coverage" the resource block's own comment was written about, so leaving them off is a real gap rather than tidying.

The shape of a fix

A predicate-counting export beside checksum_nauvis, something like:

pub extern "C" fn nauvis_field_hits(len: usize, field: u32, mode: u32) -> u32

where mode selects > 0, == 10, > ENEMY_BASEMENT + 100 and so on - the four predicates the seven guards between them need. resolvedTileIndex's range check needs a fifth answer (integral and inside 0..21), and the two name-order guards need the module to expose its field names rather than only nauvis_field_count().

Vulcanus did not need this: its guards were expressible as comparisons between folds (two slider settings, two windows, on-grid against off-grid), so #227 re-based them onto the engine and they still assert the same frozen counts - 50 of 74 fields moving with the sliders, all 74 moving with the window. See test/wasmVulcanusParity.spec.ts. Nauvis's are the ones that count positions rather than compare folds.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions