Skip to content

Release 1.0.3 - #19

Merged
CoderGamester merged 29 commits into
masterfrom
develop
Aug 4, 2026
Merged

Release 1.0.3#19
CoderGamester merged 29 commits into
masterfrom
develop

Conversation

@CoderGamester

@CoderGamesterCoderGamester commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Changed:

  • Added the com.unity.test-framework.performance (3.5.0) dependency so the package's test assemblies compile when tests are enabled.
  • Improved public API documentation and automated coverage across the data, observable, serialization, configuration, and math utilities.

Removed:

  • BREAKING — Removed the unused public IConfigBackendService interface. Consumers that implemented it must remove the implementation or vendor the two-method interface locally.
  • Removed the unused com.cysharp.unitask dependency from the runtime assembly and Migration sample.

CoderGamesterand others added 5 commits April 27, 2026 10:10
… stubs
- Replace BindingFlags.NonPublic reflection with narrow `internal` test
seams: EnumSelector<T>.SetSelectionString, SerializableType<T>.
FromSerializedNames (+ extracted OnAfterDeserializeImpl to dodge
struct-boxing through ISerializationCallbackReceiver), and
UnitySerializedDictionary KeyDataInternal/ValueDataInternal/
SetSerializedLists. Runtime/AssemblyInfo.cs grants visibility to
GameLovers.GameData.Editor.Tests.
- Add 1 High + 12 Medium-confidence audit stubs across MigrationRunner,
floatP, MathfloatP plus new SortedListExtensionsTest and
ReflectionExtensionsTest fixtures.
- Restructure MigrationRunnerTest (mocks-at-top + section dividers,
no #regions) and remove the speculative Tests/Editor/Regression/
placeholder per categories.md §2.7.
- AGENTS.md: document struct-boxing pattern + internal seams + the
System.Collections.IEnumerable qualification gotcha for ConfigsProvider.
- Add .audit-history.md persisting the unity-tests-audit run.
Made-with: Cursor
- 4 new test files (ConfigTypesBinder, ValueDataConversion, ConfigExportService, ObjectExtensions)
- 6 extended fixtures (ObservableField, SerializableType, MathfloatP, floatP, MigrationRunner, ReflectionExtensions)
- Pow2 stub corrected (Pow2(f) = f² per Referee correction)
- .audit-history.md now gitignored (local skill state)
Co-authored-by: Cursor <cursoragent@cursor.com>
Folds into the existing [1.0.3] section -- 1.0.3 is unreleased (max
tag 1.0.2). No package.json version bump.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@CoderGamesterCoderGamester self-assigned this Jul 29, 2026
CoderGamesterand others added 24 commits August 2, 2026 14:37
Test-suite audit. Every new or strengthened test carries an ADMIT/RCR header
naming the one-line production mutation that reddens it; each mutation below was
applied, observed red, and reverted.
Also:
- Remove IConfigBackendService (public but unimplemented, unused, untested; the
package's only UniTask consumer). BREAKING - see CHANGELOG.
- Drop the now-orphaned UniTask reference from the Runtime and Migration sample
asmdefs.
- Declare com.unity.test-framework.performance 3.5.0; both test asmdefs already
referenced Unity.PerformanceTesting unconditionally, so consumers without it
hit a missing-assembly compile error.
- Add Tests/AGENTS.md + Tests/CLAUDE.md. Sections 1-2 (ADMIT/RCR) are shared
verbatim across all six GameLovers packages.
EditMode 830/830, PlayMode 299/299.
RCR: TrustedOnlyMode_BinderBlocksUnregisteredTypes <- ConfigTypesBinder.cs BindToType — reword the rejection message
RCR: MaxDepth_PreventsStackOverflow <- ConfigsSerializer.cs ctor — delete `MaxDepth = maxDepth,`
RCR: Deserialize_TypesRegisteredFromProvider_AcceptsThemAndTheirIntKeyedDictionary <- ConfigsSerializer.cs RegisterAllowedTypesFromProvider — change the loop source to Enumerable.Empty<Type>()
RCR: Deserialize_TypeNotRegisteredByProvider_ThrowsAndDoesNotConstructIt <- ConfigsSerializer.cs RegisterAllowedTypesFromProvider — replace the loop body with an allow-everything shortcut
RCR: Observe_WhenFieldIsDirty_RecomputesBeforeAddingObserver <- ComputedField.cs Observe — delete the `Recompute();` inside `if (_isDirty)`
RCR: GetSelection_NonContiguousEnum_ReturnsAuthoredValue <- EnumSelector.cs static ctor — change `EnumDictionary[EnumNames[i]] = EnumValues[i];` to `= (T)(object)i;`
RCR: GetSelectedIndex_NonContiguousEnumWithNegativeMember_ReturnsCorrectArrayPosition <- EnumSelector.cs static ctor — change `EnumDictionary[EnumNames[i]] = EnumValues[i];` to `= (T)(object)i;`
RCR: GetValid_OnDestroyedUnityObject_ReturnsNullSoNullConditionalWorks <- ObjectExtensions.cs GetValid — change `return obj != null ? o : default;` to `return o;`
RCR: Dispose_OnDestroyedUnityObject_ReturnsNoneAndDoesNotThrow <- ObjectExtensions.cs Dispose — delete the `if (!gameObject.TryGetValid(out gameObject))` early return
RCR: GetAutoName_WhenSourceFileIsUnavailable_FallsBackToKindAndDoesNotThrow <- ObservableDebugRegistry.cs GetAutoName — change `string memberName = kind;` to `= "";`
RCR: Remove_WhenKeyDoesNotExist_DoesNotNotifyObservers <- ObservableDictionary.cs Remove — delete the early return in the TryGetValue/Remove guard
RCR: StopObserve_WhenCalledOnce_RemovesOnlyOneObserverInstance <- ObservableDictionary.cs StopObserving — delete the `break;` after `_updateActions.RemoveAt(i);`
RCR: Observe_WhenObserverUnsubscribesItselfDuringNotification_DoesNotThrowOrSkipOtherObservers <- ObservableDictionary.cs Clear — change `var listCopy = _updateActions.ToList();` to `= _updateActions;`
RCR: Observe_WhenObserverAddsAnotherObserverDuringNotification_NewObserverNotInvokedForCurrentUpdate <- ObservableList.cs RemoveAt — change the backward loop to `for (var i = 0; i < _updateActions.Count; i++)` (live bound)
RCR: Remove_WhenKeyExists_RemovesFromOriginDictionaryAndNotifies <- ObservableResolverDictionary.cs Remove — delete `if (!Dictionary.TryGetValue(key, out var value)) return false;`
RCR: Remove_WhenKeyDoesNotExist_ReturnsFalseAndLeavesOriginDictionaryIntact <- ObservableResolverDictionary.cs Remove — delete the same TryGetValue guard
RCR: FindMethodByName_OnDerivedType_WalksBaseTypeChainAndCaches <- ReflectionExtensions.cs FindMethodByName — delete `methods.Add(hash, methodInfo);`
RCR: GetWorldCornersArray_OnRotatedRectTransform_ReturnsCornersInWorldSpace <- UnityObjectsExtensions.cs GetWorldCornersArray — change `corners[i] = matrix4x.MultiplyPoint(corners[i]);` to `corners[i] = corners[i];`
RCR: ObservableField_HighFrequencyUpdates_FrameTimeImpact <- (benchmark, inverted)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ed §2)
§2 declared any test without an RCR line "suspect by default", but some correct
tests provably have no one-line mutation - double-guarded validation, where an
unconfigured object trips two independent guards so disabling either leaves the
other throwing. The rule was mislabelling tests that are right and unbreakable.
Adds an UNFALSIFIABLE exemption on §13's terms: the reason must be falsifiable,
must name both guards, and must record that a mutation was tried and observed
green. "Couldn't find one" is explicitly not a reason - that is an unfinished
RCR, not an exemption.
Also adds a verdict table for tests that resist mutation, because they are not
one problem: A5 duplicates get deleted (naming the surviving sibling), D2
overclaims get a strengthened assertion or an honest rename, and UNFALSIFIABLE
tests are kept with the exemption comment. The class must be proven before
acting - an A5 duplicate by observing the sibling's mutation redden both, a D2
overclaim by observing the implied mutation leave the test green.
§1 and §2 remain byte-identical across all six packages.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Section 2's verdicts table gains a fourth class. UNFALSIFIABLE was absorbing tests
that section 1's A3 rule would never have admitted - the tell being reasons like
"no line in Runtime/ participates" or "these are C#'s zero-init values", which
describe a test that pins nothing rather than one that is hard to break.
New rule: if no line in Runtime/ or Editor/ participates in the assertion, it is an
A3 reject and the verdict is delete. UNFALSIFIABLE stays reserved for behaviour this
package genuinely owns but cannot be broken one line at a time.
Sections 1-2 are shared verbatim across all six Tests/AGENTS.md; no test or
production changes in this package.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Section 13 now carries a dated baseline for this package's runtime assembly, plus
the reason to steer by that number rather than the combined one.
Every earlier coverage figure in this repo was an artifact and must not be compared
against:
- reports before today ran without -debugCodeOptimization, so Unity compiled Release
and emitted ~40% fewer sequence points (MathfloatP showed 637 coverable lines
instead of 1002) - a silently shrunken denominator
- some runs leaked test and sample assemblies into scope, and some covered only 3 of
the 6 packages
The current run covers all 11 production assemblies with none leaking, verified via
the MathfloatP denominator check now documented in Tools/coverage.sh.
Repo-wide: runtime 73.9%, Editor 5.5%, combined 41.0%. Editor is 48.1% of all
coverable lines and is accepted-untestable per the ACCEPTED (iii) rows in section 13,
which is the whole reason the combined figure is not the one to track.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sections 1-2 are shared verbatim across all six packages; this adds a sixth admission
question and the worked instance behind it.
A6 asks whether an assertion's outcome would change if project configuration changed -
a renderer feature installed or removed, an Addressables catalog built, a sample
imported. If so the test must READ that state rather than assume one value of it.
A6 is not A3. A3 asks whether the package computed the value; A6 asks whether the test
assumed which value it would be. A test can satisfy A3 and still fail A6, which is
exactly how the gap went unnoticed: UiBackdropBlurPresenterFeatureTests read a
package-computed flag (UiBackdropBlurRendererFeature.IsInstalled) but hard-coded the
expectation that it was false. Batchmode never instantiates the URP renderer, so the
flag was false there and all five tests passed; in the Editor the feature registers from
the project's renderer asset and all five failed. The fixture was asserting a fact about
the repo, not about the code under test.
Validated against the existing corpus before being written, per root AGENTS.md 2.2: the
blur fixture was the only violation and is already fixed. AddressablesUiAssetLoaderTests
asserts on a key that is unresolvable either way, and UiCameraStackFeatureTests builds
its own cameras rather than reading project renderer state.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
NUnit reuses a single fixture instance for a whole class, and this [SetUp] built
the observables from _mockInt without resetting it. ValueSetCheck writes
_mockInt = 5, so that value leaked into whatever ran next.
Nothing was failing, but only by alphabetical accident: ValueSetCheck sorts last,
so no test currently follows it. Any test whose name sorts after "ValueSetCheck"
would have silently inherited 5 instead of 0 - and so would every test in the
fixture if these methods are ever renamed to the Method_Condition_ExpectedResult
convention required by Tests/AGENTS.md §5. That rename was blocked on this.
Verified in both directions with a temporary probe test named to sort last and
assert _mockInt == 0: RED before the fix (the leak is real, not theoretical),
GREEN after. Probe removed; fixture 18/18.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…th and misc
Four slices, 287 mutations, every one observed RED and reverted; all production files
byte-identical afterwards. EditMode 826/826, PlayMode 299/299.
- observables 107/107, configs 61/61, math 82/82, misc 37/37, PlayMode 2/2.
- No holdbacks: every mutation behaved as predicted on the first pass.
Two things worth recording for whoever reads these next.
The observable classes are near-identical across List/Dictionary/HashSet, so the same
mutation text exists in three files. Every anchor is file-scoped; a bare-name or
bare-text anchor here silently mutates the wrong class and the resulting red attributes
to the wrong test.
MathfloatP mutations were sized against each fixture's tolerance rather than chosen for
elegance: _epsilon is 0.001f, so edits had to move the result further than that (Sin
numerator halved, Exp scale negated, Log2 base changed). Where a shared helper would have
reddened many siblings, the call site was mutated instead - Floor's negative branch rather
than Floor, Clamp01's call site rather than Clamp01.
Smoke fixtures carry the section 1 directory exemption instead of a mutation, naming which
fixture pins the same symbols properly.
45 tests were left unannotated on purpose. They are the A3 rejects, A5 duplicates and D2
overclaims the drafting pass identified, and they need a verdict (delete / strengthen /
keep-with-exemption) rather than a comment. The largest clusters: 5 of 8
UnitySerializedDictionaryTest tests exercise only inherited Dictionary members the class
never overrides, and the four ObservableDictionaryTest StopObserv* tests register global
observers while the fixture leaves ObservableUpdateFlag at KeyUpdateOnly, so the fan-out
they check never runs and DidNotReceive passes either way.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Concludes the RCR backfill for this package. Deletes only what the evidence supports
and keeps everything it does not.
Deleted (A3 - no line in Runtime/ or Editor/ participates, so no mutation can ever
redden them; section 2's proof standard for A3 is inspection):
- Five UnitySerializedDictionaryTest cases (Add_StoresKeyValue,
Add_DuplicateKey_ThrowsArgumentException, Remove_ExistingKey_ReturnsTrue,
TryGetValue_Exists/NotExists). The whole 56-line UnitySerializedDictionary declares two
[SerializeField] lists, two ISerializationCallbackReceiver methods and three test seams
- Add/Remove/TryGetValue/indexer are inherited BCL Dictionary members it never overrides.
The two serialization-callback tests remain and are the real coverage.
- Five *_NotObserving_DoesNothing cases across ObservableField/List/Dictionary. No observer
is ever registered, so the delegate list is empty at construction and DidNotReceive() is
fixed regardless of any production edit (section 1, D1).
Deleted (A5, probe-confirmed): SerializableTypeTest.Equals_DifferentType_ReturnsFalse -
survivor named in the manifest below.
KEPT DELIBERATELY - five A5 candidates whose duplicate claim was never probed:
Validate_UsingBuilder_DefaultValues_PassValidation, GetConfig_Singleton_ReturnsCorrect,
both copies of SecureMode_TypeNameHandlingNone_Verified, ChainedComputed_DeepHierarchy.
The reason is measured, not cautious by temperament. Of the ten A5 candidates that WERE
probed across this repo, seven turned out to have a unique pin - a 70% error rate on
inspection-based A5 classification. Every wrong classification in the pass was an A5;
none was an A3. Applying that rate to unprobed candidates predicts ~5 wrong deletions out
of 7, so they stay until a probe says otherwise.
EditMode 806/806, PlayMode 295/295.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…it proved
First trustworthy coverage figure for this repo. Regenerated with -debugCodeOptimization,
all 11 GameLovers assemblies in scope, test and sample assemblies excluded. Repo-wide
runtime coverage is 74.1% (6609/8922).
Do not compare against any earlier number. 41.8% was stale, wrongly scoped to 6 assemblies,
and diluted by Editor code; 38.3% was compiled in Release, which silently shrank the
denominator ~40%. The register now names the sanity check that catches a repeat: MathfloatP
must report ~1002 coverable lines, not 637.
The OPEN rows added here are findings the mutation pass PROVED rather than suspected - each
one is a mutation that was applied and observed leaving its test green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
All four registered GLOBAL observers and then asserted DidNotReceive(), but the fixture
left ObservableUpdateFlag at the constructor default KeyUpdateOnly - under which Add,
indexer-set and Remove skip the _updateActions fan-out entirely. The assertion therefore
passed whether StopObserving worked or not. Each was observed staying GREEN against the
removal mutation that should have reddened it.
Fix is one line per test: set ObservableUpdateFlag.Both, matching the already-annotated
sibling StopObserve_WhenCalledOnce_RemovesOnlyOneObserverInstance which had it all along.
Re-verified after the change - the mutations that previously stayed green now redden:
RCR: StopObserveCheck <- ObservableDictionary.cs StopObserving disable the `_updateActions[i] == onUpdate` removal (RED, also reddens StopObserve_WhenCalledOnce)
RCR: StopObservingAllCheck <- ObservableDictionary.cs StopObservingAll disable the `.Target == subscriber` global removal (RED, radius 2)
RCR: StopObservingAll_MultipleCalls_Check <- covered by the same `.Target == subscriber` mutation; shared-path, the multiple-registration claim is its increment
RCR: StopObservingAll_Everything_Check <- ObservableDictionary.cs StopObservingAll drop `_updateActions.Clear();` from the subscriber == null branch (RED, isolated)
EditMode 806/806.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both assertions were unfalsifiable. `Contains("\"Color\":")` matched the FIELD NAME and sat
behind an `||`; `Contains("\"x\":")` holds under default Newtonsoft serialization of a Vector
even with every converter removed. Now asserts the `#FF0000FF` hex form ColorJsonConverter
actually emits, plus IsFalse on `"normalized"` as a guard that the vector converters are
engaged.
RCR: Serialize_UnityTypes_SerializesCorrectly <- ConfigsSerializer.cs ctor remove `new ColorJsonConverter(),` (RED, verified)
A second candidate mutation - removing Vector3JsonConverter - was deliberately NOT recorded.
It reddens by JsonSerializationException (self-referencing loop on Vector3.normalized, whose
value equals its owner so Newtonsoft's cycle check trips) rather than by assertion, and
section 2 excludes red-by-exception. The guard assertion stays; the claim does not.
EditMode 806/806, PlayMode 295/295.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The four StopObserv* fixtures now set ObservableUpdateFlag.Both before registering their
global observers, so Add / indexer-set / Remove reach _updateActions. All four were observed
RED against removal of the fan-out; before c111ba2 all four were GREEN under the same
mutation, which is what made the row OPEN.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
§13 asserted every named symbol was 'either ACCEPTED or OPEN' while four packages had
already grown CLOSED rows — the spec forbade rows it contained. CLOSED is now first-class,
and it carries a contract: name the commit AND the observation, including the environment
the observation came from. A row closed on 'the fix landed' is still OPEN, because the fix
is the edit and the closure is the evidence.
Second rule: closing a row means re-deriving its claim against current source, never
reading the commit that claimed to fix it. A partial fix and a complete one produce the
same green suite and the same confident commit message, so the commit cannot be evidence
for its own completeness.
§1 and §2 are shared verbatim across all six packages; §13's preamble is too.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… never applied
Six gamedata tests were probed and observed RED during the backfill, but the annotation
never reached the source: annotate.py's dedupe scanned a fixed character lookback that
reached into the PREVIOUS test's comment block and reported 'already annotated', silently
skipping tests that had none of their own.
Recovered from the harness records rather than re-derived, and gated strictly on a
recorded RED-OK verdict for that test - prepared text also existed for 28 tests with no
recorded observation, and writing those would have fabricated a verified claim.
Comment-only diff; no test body or production line changed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… unowned-edit measurement
Tests/AGENTS.md section 2 said a test with no // RCR: line is a suspect by default, without
carving out Smoke/. Section 1 already exempts that directory (its defect class is "the assembly
no longer loads", which has no one-line mutation), so the omission flagged those fixtures
forever. Exemption is now explicit, on the same directory basis.
Also records that "unannotated" is three states, not one: observed RED with the write-back
lost, seen reddening only as collateral, or never probed. Only the last needs a probe, and
prepared annotation text must never be written without a matching RED-OK - it exists for tests
that were never probed, and writing it fabricates a verified claim.
Adds a section 13 row for the measured count of production edits that redden only collaterally
(223 repo-wide, from .test-all/rcr/unowned-edits.json). Recorded with the caveat that it is NOT
that many missing tests: for foundational primitives and the UiService integration hub, having
no isolated owner follows from centrality, not neglect.
Mechanical pass, no behaviour change.
Removed, per §6.6's rule that private members and all constructors are never
XML-documented:
- the ConfigMigrationAttribute, ConfigTypesBinder and ConfigsSerializer ctors
- the private floatP._raw field
- the private floatP.clz and ObservableDebugRegistry.TryExtractMemberName
helpers, both keeping their rationale as a `//` comment
Folded <param> tags into their summaries where the declaration is not public
consumer-facing API: DependencyGraphElement.SetTarget (Editor assembly) and the
internal ObservableDebugRegistry.Register.
Converted the SerializationSecurityMode members to inline `//` comments. Their
combined 8 lines of <summary> carried one caveat worth keeping — Secure is
serialize-only and cannot round-trip — so that is now a <remarks> on the enum
itself rather than lost with the member docs.
Added `/// <inheritdoc />` to overrides whose base documentation already exists:
ToString/Equals/GetHashCode on floatP, ToString on Pair / StructPair /
MigrationInfo, and all eight WriteJson/ReadJson in VectorJsonConverters.
Moved the internal SerializableType<T>.FromSerializedNames test seam above the
private block (§6.6: `internal` is never interleaved with `private`). Pure
reorder — the OnAfterDeserializeImpl struct-boxing pattern this package's
AGENTS.md §4 warns about is untouched, and the method still appears exactly once.
Tools/style-audit.py reports 0 remaining mechanical-class violations for this
package. The 3 findings left are overrides whose own base declarations are
undocumented; adding <inheritdoc /> there would yield empty IntelliSense, so
they are handled with their bases in the prose pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…lue pins
The four MathfloatP determinism tests each evaluated one expression twice and compared the
results, so no production edit could redden them - their own comments said "A3 reject" and
"D2 overclaim" under an "// RCR: none exists" heading, which is the laundering section 2 warns
about. They now assert golden RawValue literals harvested from the reference implementation,
which is what makes the determinism claim testable: a platform or an approximation that
computes differently fails here.
Values sanity-checked against real math before pinning - Sin(0.5)=0.4794, Cos(0.5)=0.8776,
Tan(0.5)=0.5463, Sqrt(2.5)=1.5811, Log(2.5)=0.9163, Exp(2.5)=12.18 - so they are computed
output, not captured noise.
RCR: Determinism_VerifyRawValues <- MathfloatP.cs Sin Bhaskara constant 0x42456460 -> 0x42456461
(RED, 1090413845 -> 1090413844)
RCR: AllTrigFunctions_RawValueConsistent <- same Sin constant (RED on the Sin row); Cos ->
Sin(x) (RED on the Cos row)
RCR: AllPowerFunctions_RawValueConsistent <- MathfloatP.cs Sqrt exponent unbias m -= 127 ->
m -= 126 (RED, 1070228162 -> 1074731965)
RCR: CrossPlatform_Determinism_ComplexExpression <- MathfloatP.cs Cos Sin(x + RawPiOver2) ->
Sin(x) (RED, 1065965998 -> 1075700924). Negative result recorded on the test: the one-bit Sin
constant change that reddens the three siblings leaves this one GREEN, because rounding in the
wider expression absorbs it.
Also deletes floatPTests.ExplicitConversion_ToFloat as a proven A5 duplicate. Mutating
operator floatP(float) to f * 2f reddened it and ImplicitConversion_FromFloat with identical
expected and actual values (2.46 for 1.23); ImplicitConversion_FromFloat is the survivor.
MathfloatP.cs and floatP.cs restored byte-identical (md5 verified). Editor EditMode 805/805.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ObservableDebugRegistry.Entry.ToSnapshot is `public`, but `Entry` is a `private`
nested class, so the method is unreachable from outside the registry. §6.6 keys
its never-document rule on effective accessibility rather than the declared
modifier, which makes this private — and the summary only restated the method's
own name in any case.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Completes this package — Tools/style-audit.py reports 0 items, and 0 repo-wide.
floatP was the bulk of it, and the summaries carry what the signatures could not:
- Equals treats NaN as equal to NaN, and positive zero as equal to negative zero
— deliberately unlike the == operator. That is what makes the type usable as a
dictionary key, and it is invisible from the signature.
- < and > return false whenever either operand is NaN, per IEEE, which is the
opposite convention to Equals in the same type.
- ToString formats via float, so precision beyond binary32 is not preserved.
- The internal RawMantissa / Mantissa pair differ by whether the implicit leading
one is restored.
Also documented: the validation attributes, recording that RangeAttribute passes a
null value and so needs pairing with RequiredAttribute; ObservableUpdateType and
ObservableUpdateFlag; ComputedTracker's thread-static stack, which is how a
dependency read attaches itself to the computed field currently evaluating; the
observable and configs debug-registry snapshot surfaces (cross-referencing
AGENTS.md §4 rather than restating it); the Vector*Serializable conversions; the
internal test seams FromSerializedNames / SetSelectionString / SetSerializedLists,
each recording why the public API cannot reach that state; and the Config Browser's
editor events.
Added the missing <summary> to the three interface InvokeUpdate members that
carried only <remarks> — a doc block with no summary shows nothing in IntelliSense.
Verified: batchmode green — EditMode 805/805, PlayMode 295/295, 0 CS warnings in
the -runTests log. Structural scans clean: 0 doc comments misplaced after an
attribute, 0 malformed summary blocks, 0 BOM changes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Unity's packer uses .gitignore as its pack-ignore list, so listing .github/
drops the CI workflow from the tarball while git keeps tracking it (gitignore
does not untrack existing files). Verified on a real clone: 434 -> 433 entries,
.github 1 -> 0, Runtime unchanged.
@CoderGamester
CoderGamester merged commit 3c61478 into masterAug 4, 2026
1 check passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@CoderGamester