Commit graph

2,753 commits

Author SHA1 Message Date
Meta Vens
6b107c1adc cultnet-ts: Rust-generated Idunn runtime fixtures
Expected, Activation, identities and signed presence vectors from the cultnet-rs
example; the README says how to regenerate them.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 02:05:14 +02:00
Meta Vens
95f04c1efb Rust: name the record and the version when a store is refused
PersistedRecord refuses a fifth slot naming its key and schema id, and an
unknown cultcache.store.* header no longer falls through to the legacy
envelope decode that hid the cause.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 02:04:34 +02:00
Meta Vens
c8777fe08d Python: refuse unknown store headers and extra record slots by name
Delete the raw_record[:4] slice and the legacy-envelope fallthrough for
unknown cultcache.store.* headers.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 02:04:34 +02:00
Meta Vens
569d668141 TypeScript: refuse unknown store headers and extra record slots by name
The store reader and the inspector share one header and record-slot rule;
an unknown cultcache.store.* header no longer falls through to the legacy
envelope decoder.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 02:04:34 +02:00
Meta Vens
98ed042fcc C#: refuse unknown store headers and extra record slots by name
Delete the trailing Skip loop in the record reader, the ?? v1 header default,
and the mesh reader's copy of the record decoder. The single-file store and
CultMesh single-file reads accept cultcache.store.v1 only. Persistence-format
and parity docs state the rule.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 02:04:33 +02:00
Meta Vens
2cb694d612 Pin the C0 refusal vectors shared by every runtime
An unknown store header, a record slot beyond four with a full payload, the
v2 variant record C1 will write, and a v1 store written by the base-commit
Python writer. Every runtime's tests read these bytes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 02:04:33 +02:00
Meta Vens
69a21bb057 Record the operator's rulings on document variants Q1-Q7
Q3 is ids everywhere, minted on load (not opt-in). Q4 is soft drift for
dangling overrides, which supersedes one of the target's refusals. The
others were ruled as recommended.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 01:55:09 +02:00
Meta Vens
9ba6ac4a2e cultnet-rs fixture example: name an Odin port a dev machine does not run
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 01:44:04 +02:00
Meta Vens
f5c597a81d cultnet-rs fixture example: remove the store lock files it leaves
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 01:40:30 +02:00
Meta Vens
eec1e40c25 cultmath: pin that a fixed column is never released
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 01:38:56 +02:00
Meta Vens
1e86bf0dc3 Place the document variants target and cut map on main
The target (2026-09-17, with the operator's rulings) lived only on
codex/document-variants. The cut map is Imagination's pass of 2026-09-29.
Its operator questions Q1-Q7 are open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 01:34:42 +02:00
Meta Vens
60c3d6fb0d cultmath: BoundedLeastSquares primal active-set solver
Dense small bounded LS, zero allocation, caller workspace, C#-only.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 01:33:08 +02:00
Meta Vens
0e7d2204cd cultnet-rs: example generating Rust-owned Idunn runtime fixtures
Real enrolled identities, a validated Expected, an Activation issued by
IdunnRuntimeActivationLaunch, bundle files through the CultCache store, and
runtime-presence vectors signed by the Rust signers and run through
authenticate/correlate before they are written. cultnet-ts tests will commit
the output.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 01:32:57 +02:00
Meta Vens
de57d8dc9c Merge the Idunn TypeScript runtime into main (route continuity Q6)
The operator ruled Q6 (a) on 2026-09-29: this branch lands on main before
route continuity cut C1 changes it. What lands is the ten 09-28 commits
that StreamPixels pins at 542ddd3, plus the Soul-gated fixes:
- runtime presence and daemon-health details are bounded by UTF-8 bytes
  through one helper, made well formed first, matching the Rust owner's
  len() > 512;
- the dead readAuthorityRecordBytes is deleted;
- the TypeScript packages require Node >= 20.

Soul confirmed byte-level wire parity with Idunn's Rust owners on real
Rust-written bundles, including the full write-lease flow. cultnet-ts has
90/90 tests on node:24. Capability-floor split authority, forced active
and the http-only route filter are recorded for C1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 01:21:49 +02:00
Meta Vens
0791e1b7d0 Raise the TypeScript packages' Node floor to 20
Some checks failed
CultMesh portability and performance / ubuntu-latest one-command multiplayer onboarding (push) Has been cancelled
CultMesh portability and performance / windows-latest one-command multiplayer onboarding (push) Has been cancelled
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (push) Has been cancelled
CultMesh portability and performance / windows-latest reactive semantics and leases (push) Has been cancelled
The UTF-8 detail bound calls String.prototype.toWellFormed, which
Node 20 introduced. Node 18 reached end of life in April 2025, and CI
runs Node 24. All four TypeScript packages move together so the family
keeps one floor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 01:21:18 +02:00
Meta Vens
a957f07539 cultnet-ts: one UTF-8 byte bound for presence and daemon health detail
signed-daemon-health sliced detail at 512 UTF-16 units while the Rust owner
counts bytes, so 300 x "é" failed shape validation. truncateUtf8Bytes now
serves runtime presence and both daemon-health sites, replacing
truncateRuntimePresenceDetail. It makes the string well formed first, so a
lone surrogate becomes U+FFFD instead of invalid UTF-8 in msgpack. The
unsigned payload is extracted as unsignedDaemonHealthPayload so it can be
tested without a socket.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 01:19:41 +02:00
Meta Vens
8e578ea2ab cultnet-ts: delete unused readAuthorityRecordBytes
Never called; removed with nothing else depending on it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 01:12:15 +02:00
Meta Vens
8b8650221b cultnet-ts: bound runtime presence detail by UTF-8 bytes
The Rust owner refuses detail over 512 UTF-8 bytes; TypeScript counted
UTF-16 units, so 300 x "é" was signed and then refused, and a slice inside a
surrogate pair produced invalid UTF-8. One helper,
truncateRuntimePresenceDetail, now cuts on a code point boundary at 512
bytes and serves both the publisher and validateRuntimePresence.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 01:12:15 +02:00
Meta Vens
8a66b1d230 Commit the Rust-written content vectors and document the Rust content path
content-vectors.rs-written.json is written by cultnet-rs and is identical
to the reference's file. transport-planes.md and content-sessions.md name the
Rust runtime's content path as the explicit compatibility path on the session
the client already holds, lasting until an authenticated content connector
exists behind the same fetch_content owner; runtime-parity-scope.md gets the
evidence row.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 00:51:55 +02:00
Meta Vens
11485fb491 Pin the content plane against the reference's bytes
content-vectors.cs-written.json is written by CultMeshContentVectorTests on
Linux, and includes the answers CultMeshLegacyRudpContentServer gives, so the
failure spellings are the reference's. tests/content.rs judges it. The
rs-written mirror follows in the next commit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 00:49:58 +02:00
Meta Vens
29c3e4c2b5 Add the content plane to cultnet-rs: chunk messages, pack, answer, verified fetch
ContentChunkRequest/Response join CultNetMessage on the raw path, byte
identical to the reference's field order. content.rs owns normalize_hash,
pack_content, validate_manifest, answer_content_chunk_request and
fetch_content, mirroring CultMeshCdn and CultMeshLegacyRudpContentServer.
The C# vector test is added here; the vector files and Rust tests follow.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 00:48:13 +02:00
Meta Vens
542ddd3e58 Bind runtime presence to route challenges 2026-09-28 03:54:21 +02:00
Meta Vens
265f716391 Expose published Idunn presence snapshots 2026-09-28 03:29:01 +02:00
Meta Vens
02f13527eb Use explicit Ajv ESM entrypoint 2026-09-28 02:51:12 +02:00
Meta Vens
564d5bf732 Fix Idunn runtime presence RUDP publication
Some checks failed
CultMesh portability and performance / ubuntu-latest one-command multiplayer onboarding (push) Has been cancelled
CultMesh portability and performance / windows-latest one-command multiplayer onboarding (push) Has been cancelled
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (push) Has been cancelled
CultMesh portability and performance / windows-latest reactive semantics and leases (push) Has been cancelled
2026-09-28 02:11:12 +02:00
Meta Vens
2c5dc3e278 Decode Idunn identity byte vectors 2026-09-28 01:00:52 +02:00
Meta Vens
5dd25718af Read Idunn identity envelope format 2026-09-28 00:52:03 +02:00
Meta Vens
5697802dbf Read inherited Idunn descriptors directly 2026-09-28 00:35:15 +02:00
Meta Vens
71aa615d93 Allow systemd descriptors in PID namespace init 2026-09-28 00:24:02 +02:00
Meta Vens
21dfd83211 Validate systemd descriptor PID across namespaces 2026-09-28 00:10:26 +02:00
Meta Vens
0bedcdeb37 Add TypeScript Idunn runtime presence publisher 2026-09-27 20:55:49 +02:00
Meta Vens
c9dabbeef6 cultmath: fix stale test-name references in snoise_grad/fbm_grad/ridged_grad comments
The doc comments named test classes/methods (SnoiseGradTests, FbmGradTests,
RidgedGradTests) that were never committed under those names; the actual
coverage lives in NoiseGradTests. Point the comments at the real methods.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 03:05:08 +02:00
Meta Vens
bbf00394de tests: behavioural coverage for snoise_grad, fbm_grad, ridged_grad
snoise_grad.w is bit-equal to snoise (stronger than the spec's 1e-6
floor, measured over 20,000 points). fbm_grad/ridged_grad with 1/3
octaves are pinned bit-exact against a closed form built with the same
incremental gain/lacunarity multiply chain the production loop uses,
catching both a swapped-argument mutant and an applied-once mutant.
The shared invariant-8 property harness central-differences all three
functions' own .w, filtering simplex-lattice seam flukes by comparing
the estimate at two step sizes (measured tolerances and detection
floor in the harness comment). A dedicated fixture bisects to a snoise
zero crossing and pins that ridged_grad's two one-sided gradients there
have opposite sign.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 02:54:17 +02:00
Meta Vens
256f8e20be tests: cover snoise_grad, fbm_grad, ridged_grad mirrors in HLSL compat test
Adds explicit function-presence assertions and bumps the reflective
bit-parity oracle's expected mirror count from 30 to 33 now that the
three new cultmath_ mirrors are covered automatically.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 02:54:17 +02:00
Meta Vens
03f0ed7a0a docs: describe snoise_grad, fbm_grad, ridged_grad in cultmath design.md
Extends the invariant-8 primitives list with the new gradient-noise
family: the constant-retargeting for snoise_grad, the per-octave
frequency/amplitude chain rule, ridged_grad's deliberate zero crease,
and the octave clamp's reason (the HLSL mirror test's bit-parity
oracle).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 02:37:05 +02:00
Meta Vens
1249167989 cultmath: mirror snoise_grad, fbm_grad, ridged_grad to HLSL (cut 2a-ii-a)
cultmath_snoise_grad/fbm_grad/ridged_grad mirror the new C# math
functions in both tracked CultMath.hlsl copies, which stay one blob.
Extends the existing Ashima notice entry in both THIRD-PARTY-NOTICES.md
copies to cover the ported differentiation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 02:36:59 +02:00
Meta Vens
e87dcc9ec5 cultmath: add snoise_grad, fbm_grad, ridged_grad to C# math (cut 2a-ii-a)
Analytic-gradient simplex noise, ported from webgl-noise's
noise3Dgrad.glsl differentiation but retargeted onto this repo's own
snoise(float3) constants (0.6 falloff radius, +1 permute offset, 42
scale) so snoise_grad.w stays exactly snoise's own field. fbm_grad and
ridged_grad are octave sums with per-octave frequency/amplitude
compounding (invariant 8). octaves is clamped to [0, 16] so the HLSL
mirror test's full-int32-range oracle cannot turn a garbage octave
count into a multi-billion-iteration loop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 02:36:52 +02:00
Meta Vens
268e0ef17c Merge cellular, smooth-min gradient and the struct mirror into CultMath (Asura cut 2a-i)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 02:24:47 +02:00
Meta Vens
4922438334 cultmath: correct F6 proof arithmetic and chi-square provenance in cellular docs
Soul pass 3 confirmed two documentation defects: the F6 search-radius proof
misstated 3 - 2m + 3m^2 at m=1/2 as 2.5 (actual 2.75; true min on [0,1/2] is
8/3 at m=1/3), and both math.cs and design.md cited a fabricated 203.8
chi-square statistic for float-bit hashing that Soul could not reproduce
(6+ seeds scored 7.7-30.9). Corrected the arithmetic and replaced the
unreproducible measurement with what actually pins integer hashing: the
oracle and mirror tests, and the chi-square test's real scope (the hash as
cellular calls it, not the call site itself). No test or code changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 02:23:55 +02:00
Meta Vens
05ca826091 tests: pin cellular's HLSL mirror against radius-2, 2^24, and tie inputs
EveryMirrorFunctionMatchesCSharpMath's generic random/special-value cases
never happen to hit a point where a radius-2 cell wins (about 3.5e-5 of
points) or an integer point at or past 2^23, so an HLSL mutant of cellular's
search radius, its lower-bound prune, or the removed F2=0 guard could change
cultmath_cellular's real output and still pass this test.

Adds three targeted point cases, reusing CellularAndSminGradTests' own
fixtures so the mirror test does not carry a second copy of the construction:

- the six points from AxisAlignedRadiusTwoOffsets/FindPointRealizingOffset,
  each of which realizes a different axis-aligned radius-2 offset as F1 or
  F2 in the independent 7x7x7 oracle;
- four integer points at 2^24 (both signs), where distinct cells' jittered
  features can round onto the same float32 value, reaching the F2 = 0 guard;
- one exact F1 = F2 tie point, the midpoint of two adjacent cells' feature
  points (bit-exact-equidistant from both by construction, no search
  needed).

Verified against four HLSL mutants applied to shaders/CultMath.hlsl on
scratch copies (not committed) and reverted after each check:
- `dz < 2` instead of `dz <= 2`: killed by the axis-slice point at
  (-56.671272, -67.01973, -79.001).
- `dx` starting at -1 instead of -2: killed by the axis-slice point at
  (62, -77.91331, -79.42451).
- pruning against f1 instead of f2: killed by an axis-slice point and both
  of the 2^24 integer points (3 mismatches).
- the F2 = 0 guard removed (`grad2 = (p - c2) / f2`, unconditional): killed
  by the (2^24, 2^24, 2^24) integer point (NaN vs the guarded zero).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 23:14:10 +02:00
Meta Vens
91596884b0 tests: fix hashing fixtures, false comments, and gradient tolerance
CellularAndSminGradTests.cs changes for cut 2a-i's pass-2 findings:

- FeaturePoint and the two other independent pcg3d/pcg4d call sites now hash
  int3(cell)/int4(int3(cellId), 0) to match production's integer-hashing fix
  (previous commit); the oracle would otherwise diverge from cellular() and
  every comparison test would fail.

- New JitterAndIdPassAChiSquareUniformityTest: jitter.x/y/z and id each pass
  a chi-square uniformity test (16 bins, 15 df, critical value 37.7 at
  alpha=0.001) over 200,000 cells. This is the behavioural pin for the
  hashing fix; reverting to pcg3d(cell)'s float-bit hash fails it.

- Two false comments corrected to the measured facts: the
  NearestFeatureWins test's claim that |component|=2 offsets are "provably
  never the true nearest" is false (their lower bound is 1, not sqrt(3); Soul
  measured 3 F1 wins in 2,000,000 samples), and SearchReachesEveryAxis...'s
  claim of "lower bound is exactly 2" and "zero hits in 3,000,000" is also
  false (lower bound is 1; Soul measured about 1 hit in 28,000).

- PrunedSearchIsBitIdentical... renamed to
  ...BelowTwoToTheTwentyFifth and its comment states that domain explicitly
  (design.md, previous commit).

- GradientTolerance split into SminGradientTolerance (2.5e-4f) and
  CellularGradientTolerance (1.3e-3f): the two functions have different
  curvature (smin_grad is exactly quadratic in a band; cellular's F1/F2 are
  real distance fields), so a shared 3e-4 tolerance carried almost no
  headroom over either's actual measured noise (re-measured here at 5.3e-4
  for smin's old eps, 2.0e-4/2.6e-4 for cellular), not the "~6e-5" the old
  comment claimed. smin_grad's eps moves from 0.001f to 0.01f (no truncation
  cost there; dilutes float noise 8x) with a matching widened seam-exclusion
  band so p +/- eps cannot step across the seam the check at p already
  avoided. cellular's eps stays at 0.0005f (a small sweep found it already
  near the truncation/noise sweet spot for a real distance field). Both new
  tolerances keep >5x headroom over their own measured worst case and both
  still die under a 1.01x-scale mutant on the returned gradient — smin down
  to 1.0005x, cellular (M9/M16-style, either gradient) down to 1.002x.

- GradientMatchesCentralDifferencesAwayFromTheF1EqualsF2Seam also excludes a
  band around F2 = F3 now, not just F1 = F2: the second-nearest feature's
  identity swaps there too, a genuine kink the old test could silently hit
  (an unfiltered large sample found a 0.78 edge error this way, swamping the
  ~2e-4 the filtered test actually sees).

- AxisAlignedRadiusTwoOffsets and FindPointRealizingOffset are extracted from
  SearchReachesEveryAxisAlignedRadiusTwoSlice as internal fixtures so
  HlslSourceCompatibilityTests (next commit) can reuse the same construction
  instead of a second copy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 23:13:50 +02:00
Meta Vens
cb94b74ae3 docs: correct F6 proof, integer hashing, and the prune's precision domain
design.md follow-ups matching the math.cs/HLSL fix in the previous commit:

- The F6 "5x5x5 is exact" argument is rewritten with the corrected near-side
  neighbour bound (choose the axis closest to its own boundary, not a fixed
  axis), the m <= 1/2 derivation, and the counterexample that showed the old
  argument wrong. Same text as the math.cs comment, so the two do not drift.

- "Integer hashing" now states that cellular hashes the winning cell's
  integer coordinate, not its float32 bit pattern, and records the measured
  chi-square evidence (203.8 over 1,000,000 cells, 15 df, critical value
  37.7) for why the old bit-pattern hash failed a uniformity check.

- "Precision domain" gets a new paragraph: the lower-bound prune's bit
  identity to the unpruned 5x5x5 search holds for |p| < 2^25, not
  unconditionally. Above that, cell + offset itself starts to round in
  float32, so the pruned and unpruned loops can visit different actual
  neighbours at the same nominal offset (Soul, cut 2a-i: 180 of 1,100,000
  points differ at |p| ~= 3.4e7). This is a float32 domain limit on the
  equivalence proof, not a bug in the prune; the committed test's [-50, 50]^3
  sweep is comfortably inside it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 23:13:25 +02:00
Meta Vens
9207a59280 cellular: hash the integer cell coordinate, correct the F6 near-side proof
Soul (cut 2a-i, pass 2) found two defects in cellular's own math.cs source
and its HLSL mirror:

- cellular hashed pcg3d/pcg4d over the FLOAT32 BIT PATTERN of each
  integer-valued cell coordinate (pcg3d(neighbor), pcg4d(float4(cellId, 0)))
  instead of the integer coordinate itself. Two adjacent cells' bit patterns
  share more structure (same exponent, mantissa one increment apart) than
  the integers do going into pcg3d's own mixing, and that structure survived
  into the jitter: measured chi-square 203.8 for jitter.x over 1,000,000
  cells against 15 degrees of freedom (critical value 37.7). Both call sites
  now hash int3(neighbor)/int4(int3(cellId), 0) directly, in C# and in the
  HLSL mirror (both shaders/CultMath.hlsl and the Unity copy, byte-identical
  as before). This changes cellular's noise output — nothing has shipped, so
  that is acceptable, but it is a real behavioural change, not a comment fix.

- The F6 exactness proof's "near-side neighbour" bound was wrong as written:
  picking the near-side neighbour on a FIXED axis is not always within
  sqrt(3) of the query (counterexample: u = (0.5, 0, 0) with the x-neighbour
  jittered to (-1, 1-2^-24, 1-2^-24) gives ~2.06, past the radius-2
  exclusion). The comment is rewritten to the correct argument: choose the
  axis whose u_i sits closest to a cell boundary (m = min(u_i, 1-u_i) <=
  1/2 on that axis), and the near-side neighbour on THAT axis has squared
  distance at most (1+m)^2 + 2*(1-m)^2 = 3 - 2m + 3m^2 <= 3 on [0, 1/2],
  strictly below 3 since the jitter never reaches the boundary. Margin
  2 - sqrt(3) ~= 0.268 (Soul's adversarial check: worst in-box F2 is exactly
  sqrt(3), only in the unattainable corner limit).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 23:13:09 +02:00
Meta Vens
e739ff1e52 tests: kill a single-slice loop-bound gap in cellular's 5x5x5 search
Stryker (mtp, --since 29e50ad3) found 261 survivors / 24 timeouts across the
whole repo; triaging the ones in this fix batch's own new code (cellular's
loop, its prune, cellular_unit) surfaced one real gap disguised as
collateral timeout noise from a batched infinite-loop mutant: dz < 2 (and
the dy/dx equivalents), silently dropping the +2 layer on one axis alone,
passed every existing random-sampled test. That is not the sweeps being
weak: the exactness proof's own margin (F1, F2 always < sqrt(3), radius-2
cells' lower bound is exactly 2) makes a genuine win from any single
|offset component| = 2 cell astronomically rare over uniformly random
points (measured zero hits in 3,000,000 samples).

SearchReachesEveryAxisAlignedRadiusTwoSlice constructs a real example for
each of the six axis-aligned radius-2 offsets directly: for a candidate
integer cell, build the query point that is the closest point of that
cell's own unit cube to the target neighbour's actual jittered feature.
That construction finds a hit for every offset within a couple thousand
candidate cells, deterministically. This kills dz < 2 / dy < 2 / dx < 2 (all
manually confirmed).

Also manually confirmed via Stryker's own reported mutants: the dz--/dy--/
dx-- (increment-to-decrement) mutants are genuine infinite loops, correctly
caught as timeouts. The f2 >= 0.0f mutant (disabling the F2 = 0 guard) is
killed by the existing NoNaNAtIntegerPointsNear2To24 test. The remaining
survivors/timeouts in the new code (the lower-bound prune's >>= vs >
comparison, its arithmetic terms, and cellular_unit's >> vs >>> shift on an
already-unsigned operand) are equivalent mutants: since the per-axis lower
bound is always 0 or 1 by construction, and pruning is a proven-safe
optimization that never changes cellular's output, no mutation confined to
"when does the prune trigger" can be observed by any value-based test.
Verified by hand: disabling pruning entirely reproduces the unpruned
reference bit for bit, as it must.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 21:28:36 +02:00
Meta Vens
4163001c91 Merge surface nets and face-weighted normals into GameCult.Geometry
Asura Cut 2 (GameCult/Asura docs/cut-map.md). CultGeometrySurfaceNets.Extract
emits a welded quad mesh with each quad named by the grid edge it crosses,
(cell, axis), in strictly ascending order; orientation comes from the inside
flag and a per-axis handedness table, one authority. Face-weighted normals
are area-weighted via quad diagonals. Non-finite inputs are rejected.
Stryker is scoped to GameCult.Geometry.

Closed after three Soul passes; byte-identical behaviour across the
closing refactor on 31 fixtures. The 7 GeometryDocumentTests failures
predate this merge (e420410, registry check D11) and are tracked
separately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 21:05:58 +02:00
Meta Vens
3b1ea71eef docs: correct cellular/smin_grad design.md to match fix batch 1
- smin_grad is Quilez's quadratic-polynomial smin, not cubic.
- cellular's search radius is 5x5x5 (F6), not 3x3x3; adds the exactness
  proof and the pruning claim.
- id source is now pcg4d over the winning cell, not the pcg3d hash that
  produced its jitter (F4).
- F2 = 0 is documented as reachable (past |p| of about 2^23), not
  unreachable; removes the false "unreachable" claim and adds a "Precision
  domain" note stating the float32 feature-spacing/tie behaviour honestly
  (F3, minor finding).
- The struct-mirror comparison note now says it also matches field name and
  type in declaration order, not just position (F2).

No entry added to THIRD-PARTY-NOTICES for the Quilez/Worley formulas: per
Self's standing ruling, a published formula is not ported code.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 20:40:43 +02:00
Meta Vens
f6fb589ac3 Fix batch 1 (cellular/smin_grad): exact search, decorrelated id, finite F2=0
Cut 2a-i fix batch 1, findings F1, F3, F4, F5, F6, F7 (Soul falsification of
the first landing):

- cellular now searches a provably exact 5x5x5 neighbourhood (radius 2), not
  3x3x3: 3x3x3 missed the true F2 for 9 of 400,000 sampled points. The
  comment in math.cs proves 5x5x5 always contains the true F1 and F2 (both
  are always < sqrt(3), every excluded cell is always > 2). A cheap
  position-only lower-bound prune skips the pcg3d/jitter/distance work for
  cells that provably cannot beat the running F2, without changing any
  output bit (F6).
- F2 = 0 now gets the same degenerate-gradient guard F1 = 0 already had,
  fixing a NaN that was reachable past |p| of about 2^23 (F3).
- id now comes from pcg4d over the winning cell alone, never from the pcg3d
  hash that produced that cell's jitter, so id and jitter are no longer
  deterministic functions of each other (F4).
- cellular_unit maps the top 24 bits instead of a plain divide-by-2^32, so
  the mapping is always inside [0, 1); the old formula rounded
  0xFFFFFF80..0xFFFFFFFF up to exactly 1.0f (F7).
- Central-difference tolerances tightened from 0.02 to 3e-4 (measured float
  noise at the committed eps is about 6e-5), and cellular's own gradient
  test now differentiates cellular's RETURNED .w values instead of a
  duplicate FindF1F2 search, so a mutant that corrupts only the returned
  gradient can't hide behind an independently-computed value (F1, F5).
- The struct-mirror comparison in HlslSourceCompatibilityTests now checks
  field name and declared type in declaration order, not just position, so
  a reordered-and-relabelled mirror struct (H2) or a renamed/retyped one
  (H3) both fail the walk instead of surviving on values alone (F2).
- FindF1F2 widened to a true independent 7x7x7 brute-force oracle; new tests
  pin production's exact agreement with it, the pruned search's bit-for-bit
  equivalence to an unpruned 5x5x5 reference, no NaN at 2^24, and id's
  correlation with jitter under 0.05.
- Comment/doc fix: smin_grad is Quilez's quadratic-polynomial smin, not
  cubic.

Both shaders/CultMath.hlsl and unity/.../Shaders/CultMath.hlsl stay
byte-identical.

Manually verified mutants M9 (grad1 x 1.01), M16 (grad2 x 1.01), and M18 (id
from hash.y) all die against these tests; H2/H3 struct mutants die via the
new comparator tests. Local dotnet test: 191/191 passing. FXC cs_5_0 compile
of a scratch kernel using both cultmath_smin_grad and cultmath_cellular
succeeds.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 20:40:28 +02:00
Meta Vens
d64de1b69d fix: reject non-finite isoValue and origin in Extract
samples and cellSize were validated but isoValue and origin were not:
iso = NaN or +inf silently returned an empty mesh, and origin = NaN gave
NaN positions. Extend Extract's existing top-of-method validation authority
to reject non-finite isoValue and non-finite origin components with
ArgumentException, matching the existing style, with tests for each
component.

Overflow at extreme magnitudes (cellSize ~3e38, or finite samples whose
interpolation overflows to inf) is a separate, float-domain limit rather
than a validated-input error; documented in the XML doc and provenance
notes, deliberately not range-checked.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 20:31:44 +02:00
Meta Vens
bef3d3eba3 refactor: replace TryGetOtherEndpoint's dead bool with a structural loop bound
TryGetOtherEndpoint's bool return was dead control flow: when a mutant
flipped its `return false` guard to `return true`, `other` stayed a clone
of `coord` (only one component would have been incremented on the true
path that never runs for that guard), so the caller compared a sample
against itself and behaved identically either way. That produced the
equivalent survivors at Extract's :92 continue and the guard's :198
return.

Bound the edge loop with the same condition (coord[axis] < cellCounts[axis])
directly, computing `other` inline once the bound holds. One path instead
of two that happened to agree; the helper is gone, and so is the `continue`
that used to depend on it. Behaviour is unchanged: verified with a
before/after run of the existing suite plus a temporary harness comparing
Extract's Positions/Quads/QuadEdges against ca220a5's code on sphere,
non-cubic, open-plane (each axis), checkerboard, and minimal 2x2x2
fixtures - all byte-for-byte identical.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 20:30:19 +02:00
Meta Vens
b4db5cb6ed test: cover CultGeometryGridEdge.Equals(object) behaviourally
Mutating obj is CultGeometryGridEdge other && Equals(other) to && true
passed the suite: nothing exercised object.Equals directly with a mismatched
X/Y/Z/Axis, null, or an unrelated type. Add a behavioural test that checks
each component independently, rejects null and other types, and agrees with
the typed Equals and GetHashCode.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 20:29:00 +02:00