The GLSL is generated from the HLSL by one lowering, mirrored against C# by a
committed fixture evaluated on its own arguments (portable across OSes), with
the frustum ball checked by two-sided enclosure and Phacelle by a scaled
absolute bound. design.md conflict: keeps the branch's sqrt-precision text and
drops the 6e-4 sentence interval-ops r4 removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
iv_frustum_ball widened by its derived float32 bound, envelope-then-noise
fields, the analytic constant-density body, one shipped void (Rh 198, S 50),
LOD agreement against a converged march, and the wells contract as ruled
(cultmath-tapes:ruling:wells-overhead-plus-floor). Verdict
cut-interval-ops.s3 holds; one Low finding (LodStep footprint branch unpinned)
is recorded for the next interval cut.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Measured on the shipped void and the Aetheria wells at warp 60: affine warp
spans, simplex cells and lattice points per span, exact-against-march cost and
error per octave, high-octave variance, clamp crossings and transmittance
error; plus Aetheria's triangle noise. Verdict: exact integration does not
beat sampling for optical depth on either field.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gpu-snoise-parity is Asura's FXC and Unity readback of snoise, not a GLSL run; phacelle's GLSL
evaluator is the cultmath-tapes follow-up glsl-browser-parity-run.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GoldenFixtureMatchesCSharp draws arguments only under CULTMATH_WRITE_GLSL=1: the draw calls MathF.Pow,
whose bits differ by OS. Checking decodes each committed case's arguments and evaluates C# on them.
phacelle is compared across platforms within 2^-20 max(|v|, 1) per component; iv_exp keeps one ulp.
The iv_frustum_ball check gains the upper side r + d + 2^-19 (r + |c|_1) that NoiseBoundTests pins.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The parity section states the enclosure rule, restores that the evaluator concatenates
CultMath.Phacelle.glsl for the phacelle family, and names CultLib's browser-pane run
(follow-up gpu-snoise-parity) as that evaluator. The frustum-ball bound no longer assumes
a correctly rounded GLSL sqrt: proven for C# and HLSL, measured on GLSL.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
iv_frustum_ball's sqrt is not correctly rounded on WebGL2, so its family is ulp-bounded and
its entry carries the enclosure rule the consumer applies in double; GoldenFixtureMatchesCSharp
applies it to C#'s results too. A phacelle family (normalization 0.5, platform exp, sin, cos)
is appended after iv_exp; every earlier family's cases are byte-identical.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
EveryPublicFunctionIsLowered compares (name, parameter types) after the lowering's own
step 3, so a dropped overload such as cultmath_pcg3d(vec2) fails. TwoFileHeaderContract
pins distinct guards, the MIT and MPL-2.0 provenance labels, and the MIT file's pointer
to CultMath.Phacelle.glsl. GlslLowering exposes step 3 as LowerTypeNames; output unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The release script refuses a CultMath.dll that differs from the tracked bytes
(clearing every obj configuration, CultMath source pinned to CRLF, a git
checkout required). CI publishes through one guarded entrypoint that runs the
release-checks suite first, replacing the deleted if:-condition pin (ruling
asura:ruling:suite-gate-structural-not-parsed). Verdict cut-3-gate.s4: merge;
node-env-skips-suite (Medium) and always-skips-other-gates (Low) follow before
the next release tag.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every figure is from r4's IV-REPORT lines: (a)-(d) with (c)'s oracle ceiling,
efficiency, cull fraction and probe overhead; (e) at the shipped void with the
two depth errors against the converged march; the analytic body and its pin;
the [w(z1), 1] weight-bound deviation; the contracts as asserted, (c) in the
words of ruling wells-overhead-plus-floor.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The footprint march's optical depth at the body start is measured against a
converged midpoint march (h = 0.5, every cell) and may be at most twice as
wrong as the fixed-step march; the end-of-ray assertion goes. BodyDepth owns
the body's optical depth and its pin compares depths, not transmittances.
(c) asserts probe overhead >= 0.90 and a hard cull floor of 0.5 (ruling
wells-overhead-plus-floor); the oracle ceiling, efficiency and cull fraction
are printed. WeightBoundEnclosesOneSignedNoise pins VoidField's weight bound.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scripts/release-after-suite.mjs runs the release-checks suite and then the
release action (npm publish, or the Python sdist and wheel build that the PyPI
step uploads) from one process, and releases only if the suite passed. No step
condition can release what the suite did not pass, so the pin that read if:
conditions (status functions, multi-line if:, the leading-conjunct rule) is
deleted with its tests and docs. What remains compares each job's release steps
with their expected text exactly, less their if: line, and refuses
continue-on-error, shell and defaults in the workflow.
Ruling asura:ruling:suite-gate-structural-not-parsed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GlslLowering.SeparateFiles is the one name-keyed rule: CultMath.Phacelle.hlsl
lowers into shaders/CultMath.Phacelle.glsl (MPL-2.0, guard
CULTMATH_PHACELLE_GLSL) and its include line leaves CultMath.glsl, which is
now MIT and says so in its provenance line. ReadShaderSource takes an
include predicate (one resolver); the C# mirror still inlines everything.
GlslMirrorTests pins both files, checks tokens in each, takes the union of
definitions and asserts cultmath_phacelle( and CultPhasor live only in the
Phacelle file. The fixture appends cultmath_iv_frustum_ball (exact) and
cultmath_iv_exp ("ulp-bounded, platform exp", platform named); the
comparison is per family, the platform family within 1 ulp with the
maximum printed. THIRD-PARTY-NOTICES lists CultMath.Phacelle.glsl, not
CultMath.glsl, as MPL-2.0.
Regenerated on Yggdrasil (Ubuntu 24.04.5, .NET 10.0.12); 286/286 green,
iv_exp within 0 ulp.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Regeneration alone (CULTMATH_WRITE_GLSL=1) on Yggdrasil at 8be32a2e: the
lowering of r3's widened iv_frustum_ball, 15 lines. The fixture does not
change. Full suite 286/286 green.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
README conflict resolved by keeping r3's Intervals bullet, then the GLSL
bullet. design.md and HlslSourceCompatibilityTests.cs merged clean.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
interval-ops r4 fixes verdict s2's four findings (LOD agreement against a
converged march, body depth in optical depth, the wells oracle measurement,
the WeightBound pin); its wells assertion waits on question wells-ceiling-oracle.
glsl-lowering r2 merges onto 3ac7250a.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Soul s2 found the CultMath bytes follow the checkout's line endings (an LF clone
built 53084D94, not the tracked 6781BF20) and its path when no .git maps the root
to /_/. .gitattributes pins packages/cultmath/src/** to eol=crlf, which the
tracked DLL was built from, so no re-release. The build script refuses up front
without .git, and the refusal and docs name line endings beside source and
toolchain.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Soul s2 found 'success() || c' and plain or quoted if: values continued on a
following line passing the pin. Any status function now refuses, and stepCondition
reports an if: whose value continues (block scalar or a deeper-indented next line)
as multi-line, which the pin refuses. Soul's four probe forms are asserted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Publish if: calling always(), cancelled() or failure() runs after the suite failed, the
continue-on-error bypass by another name; a block-scalar if: was compared by its indicator, so
'>-' equalled '>-' whatever followed. Both are now refused. The third refusal no longer calls
sound conditions narrower: it names the three accepted shapes, and the code comment and
docs/semver-policy.md list the sound forms textual matching refuses and why.
(Soul findings cut-3-gate.s1.status-function-bypass, block-scalar-if-compared-as-text,
pin-refusal-cost-undocumented.)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Unchanged CultMath source built on another SDK or host gives other bytes (Linux sdk:10.0:
db2a11cc against tracked 6781bf20), so the refusal no longer sends the operator to release a
CultMath with no change (Soul finding cut-3-gate.s1.toolchain-drift-named-as-source-change).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Directory.Build.props puts CultMath's obj at obj\packages\cultmath\src\CultMath, which the
obj\src-only clean left in place, so an old-mtime CultMath source change could reuse a stale
CultMath.dll and pass the byte gate (Soul finding cut-3-gate.s1.cultmath-obj-not-cleared).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Eyes pass for variants❓read-only-record-signal. ORMs, embedded
stores, serializers, file systems and object stores; signal shape and
time-of-check pitfalls for each, with evidence pointers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The suite step's if: is absent, equal to Publish's, or a leading conjunct of
a Publish condition that has no ||. A disabled or narrowed suite step fails
the pin. Closes asura:follow_up:suite-step-condition-pin.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The declared org.gamecult.cultmath dependency must equal the CultMath package
version (-ne, not -gt), and every CultMath.dll a managed publish produced must
equal the DLL that package tracks. The type-name check and its helper,
scripts/check-cultmath-types.cs, are gone: the byte gate subsumes them.
$managedPublishes is the single owner of publish-root identity for the clean
step, the publish loop, $publishedByName, the byte gate and --api-refs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The release check measures each package against its predecessor tag instead of
trusting caller-declared flags. First releases are proved by a managed assembly,
the suite runs in CI and the Unity scripts before publish, and the Caching Unity
prefix is its own tag family. Verdict asura:verdict:cut-semver-measured.s7 holds;
one Low finding (suite-step-condition-unpinned) is deferred.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
publish-packages.yml runs the suite in both jobs, after .NET setup on a full-depth
checkout and before any check or publish step; the three Unity release scripts run
it before the checker. A test reads each file and fails when the step is removed,
moved, or made non-fatal. The Caching Unity pin now needs a prefix declared once
whose exact tags hold the package's own manifest at the tag's version. No NUL byte
in the checker is a test. The policy records that releases run from a full clone.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
MarchTile reports a body start where the gated bound over the rest of the
grid is a positive point and appends the rest unprobed; MarchLod takes one
closed-form Beer-Lambert step there. AnalyticBodyMatchesFineMarch pins it
against the ungated field and the fixed-step product, and pins that no
(a)-(d) tile reports a body. VoidField takes a focal length; LOD-far
(Rh 4000, S 50, f 467) joins the enclosure test, which now asserts it
sampled weights in (0, 1) and at 0. The void grid ends at Rc + 6/K. The
doc derives the one shipped void (198, 50) and records the [w(z1), 1]
deviation. (c) is held to 0.90 of its probe-free ceiling.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The radius gains (|c|_1 + radius) 2^-20 in C# and both HLSL copies; the
doc's strictness claim leaves. TileBallEnclosesEveryRaySegment measures in
double over the r2 domain and seven extreme families with outward corner
flows, pins the radius two-sided, and counts misses per family. The noise
ball enclosure tests draw radii to 1e3.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolves Soul's five findings on cut-interval-ops.h2 and carries the rulings
operator-wells-contract-vs-ceiling and operator-analytic-wall-body. glsl-lowering
r2 and site-ground r3 now depend on interval-ops r3; the site-ground spec names
the one shipped void with (Rc, e) derived from (Rh, S) and the body-start word.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Also defines the PE fixture before the tests that use it, so a filtered run no
longer reaches it before initialization.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Monorepo snapshot tags track every package's directory, so tracking a file
proved nothing about a package's own releases. A package with an assemblies
directory is a first release only when no tag under any prefix tracks a managed
assembly there (decided by PE bytes, once per blob). Assembly-less packages are
a first release when no tag of their own prefix exists; their prefix is pinned
by the suite test tying each declared prefix to a workflow trigger or an
existing tag, which now fails on a typo for every assembly-less package.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The changelog-heading guard missed 12 of 17 heading shapes and a first changelog
entry. It and its parsing are deleted. A release with no same-prefix baseline is
a first release only when no tag in the repository, under any prefix, tracks a
file under the package's folder (declared assemblies dir, else the changelog's
directory); otherwise it refuses naming the tag. A tag whose tree cannot be read
refuses. Tests pin the mistyped prefix for CultMath 0.3.1, cultlib 1.0.61 and a
Python package, a genuine first release, the moved-folder choice, and an
unreadable ancestry and tree.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The previous release is chosen by version order among same-prefix tags strictly older than the version, and must be an ancestor of HEAD, so a later backport on another branch never moves a rebuild's predecessor. A release with no previous tag is refused when the changelog already lists an earlier version, so a mistyped prefix cannot make an unmeasured first release. The declaration is validated as a whole: two packages sharing a prefix, or an entry without a string tagPrefix and changelog, refuse.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
One owner per store decision per runtime (header, existence and links, zero-byte,
directory at path, lock, replace, soft write), with pinning tests and open gaps by
follow-up id. Written by a Modeling pass against 705ab669.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The checker reads each package's tag prefix, changelog and assemblies directory
from scripts/release-packages.mjs and derives the release record from git tags.
A first release is the absence of any older tag in a checkout that holds other
tags; a malformed same-prefix tag, a checkout without tags and an unreadable
repository refuse. The measured set is every managed assembly (CLI header in
the PE bytes) tracked at the previous tag at any depth; an unbuilt one is a
break, a built assembly with no namesake is an addition.
Deleted with their branches, refusals and tests: --first-release, --api-new,
--tag-prefix, --changelog, --api-baseline-path and the workflow first-release
decision line. Any unknown option is now a usage error.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>