Release 0.9.5 - #20
Merged
Merged
Conversation
Bumps to 0.9.5 (published at 0.9.4; this is a real release). This package had only a README.md, and that README was the unedited Unity "Package Starter Kit" boilerplate template. - New AGENTS.md, verified against every file in Runtime/: the full state-type reference (Initial/Final/State/Transition/Choice/Wait/ TaskWait/Nest/Split/Leave), the capability-interface composition pattern in IState.cs, nesting/splitting/leaving semantics, and the gotchas that fell out of reading the source closely (event identity is per-instance not per-name, Trigger is a silent no-op when not running, TaskWait cannot receive events while waiting). - New CLAUDE.md (thin @AGENTS.md wrapper). - README.md rewritten with a verified-working Quick Start example (built from the same setup pattern StatechartTest.cs uses) and real installation/API content, following the repo-wide section order. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds (or updates) Tests/AGENTS.md and its Tests/CLAUDE.md wrapper, and points the package-root AGENTS.md at it as required reading before touching Tests/. Sections 1-2 (ADMIT test-admission criteria, RCR revert-and-confirm-red) are shared verbatim across all six GameLovers packages and must be changed in lockstep. This revision anchors mutation references on file + symbol rather than file:line, which rots, and caps the on-test comment budget - change narration and investigation transcripts belong in the commit body, not on the test. No test or production code changes in this package. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… state) Second slice of the suite-wide RCR backfill. Covers StatechartTest (8), StatechartTransitionTest (4) and StatechartStateTest (6). All 17 distinct mutations were applied, observed red, and reverted by the harness; the three production files touched were verified byte-identical afterwards. Suite green at 89/89. Where two tests share one guard, the mutation is split so each pins its own half - e.g. InitialState.Validate's `_transition?.TargetState == null` covers both "no transition at all" and "transition without target", and the two tests now carry mutations that redden one and leave the other green. One dud found: State_TriggerNotConfiguredEvent_NoEffect has no single-line mutation. SimpleState.OnTrigger's miss path is a plain Dictionary TryGetValue returning false, and StatechartEvent's Equals/GetHashCode are both Id-based, so forcing a lookup hit needs coordinated edits to two members. The behaviour it pins is the BCL's rather than this package's (A3). Annotated as a review candidate rather than deleted. Overlaps are recorded on the tests that have them: the SimpleState.Exit and Statechart.Run mutations each redden several siblings, because those siblings assert the same exit hook / all call Run() first. RCR: SimpleTest (StatechartTest) <- InitialState.cs Exit fan-out loop bound i < 0 RCR: InitialState_MissingTransition_ThrowsException <- InitialState.cs Validate guard to _transition != null && _transition.TargetState == null RCR: InitialState_TransitionWithoutTarget_ThrowsException <- InitialState.cs Validate guard to _transition == null RCR: InitialState_StateTransitionsLoop_ThrowsException <- InitialState.cs Validate self-target check to if (false) RCR: InitialState_MultipleTransitions_ThrowsException <- InitialState.cs Transition duplicate guard to if (false) RCR: NoInitialState_ThrowsException <- Statechart.cs ctor InitialState null guard to if (false) RCR: MultipleInitialStates_ThrowsException <- StateFactory.cs Initial duplicate guard to if (false) RCR: MultipleFinalState_ThrowsException <- StateFactory.cs Final duplicate guard to if (false) RCR: SimpleTest (StatechartTransitionTest) <- TransitionState.cs Enter fan-out loop bound i < 0 RCR: TransitionState_TransitionWithoutTarget_ThrowsException <- TransitionState.cs Validate guard to _transition == null RCR: TransitionState_TransitionWithoutTransition_ThrowsException <- TransitionState.cs Validate guard to _transition != null && _transition.TargetState == null RCR: TransitionState_TransitionsLoop_ThrowsException <- TransitionState.cs Validate self-target check to if (false) RCR: SimpleTest (StatechartStateTest) <- SimpleState.cs Exit fan-out loop bound i < 0 RCR: State_TransitionWithoutTarget_Succeeds <- StateInternal.cs Trigger nextState null early-return to if (false) RCR: State_TriggerNotConfiguredEvent_NoEffect <- (no single-line mutation; A3 review candidate) RCR: State_PauseRunStatechart_Success <- Statechart.cs Run delete _isRunning = true RCR: State_ResetRunStatechart_Success <- Statechart.cs Reset delete the _currentState rewind RCR: StateTransitionsLoop_ThrowsException <- SimpleState.cs Validate self-target check to if (false) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Third slice. 6 of 7 mutations verified red and reverted; suite green 89/89. Dud found: ChoiceState_MissingTransitions_ThrowsException has no single-line mutation. A choice state with zero transitions trips BOTH independent Validate guards (!hasTransitionWithCondition and noTransitionConditionCount == 0), so disabling either leaves the other throwing - verified by narrowing the first guard and observing the test stay green. Double-covered belt-and-braces. The two tests that share the !hasTransitionWithCondition guard are split so each pins its own input: one narrows the guard to require transitions, the other to require none. RCR: SimpleTest <- ChoiceState.cs OnTrigger invert CheckCondition() RCR: ChoiceState_MultipleTrueConditions_PicksFirstTransition <- ChoiceState.cs OnTrigger reverse the scan order RCR: ChoiceState_MissingTransitions_ThrowsException <- (none; double-guarded) RCR: ChoiceState_MissingConditionTransition_ThrowsException <- ChoiceState.cs Validate narrow guard to _transitions.Count == 0 RCR: ChoiceState_OnlyConditionTransition_ThrowsException <- ChoiceState.cs Validate noTransitionConditionCount guard to if (false) RCR: ChoiceState_WithoutTarget_ThrowsException <- ChoiceState.cs Validate TargetState null guard to if (false) RCR: StateTransitionsLoop_ThrowsException <- ChoiceState.cs Validate self-target guard to if (false) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Fourth slice. 9 of 14 mutations verified red and reverted; suite green 89/89. Running total for this package: 46 of 89 annotated. Harness fix landed alongside: verify.py deleted a stale results file before each run and retries when Unity produces none. Without it a failed Unity invocation silently reported the PREVIOUS spec's XML, which produced four bogus verdicts naming tests from a different fixture. Those verdicts were discarded and the slice re-verified from scratch. Five tests have no single-line mutation and are annotated as such: - WaitState_MissingConfiguration / TaskWait_MissingConfiguration - the unconfigured state in both fixtures also has no transition, so it trips two independent Validate guards; disabling either leaves the other throwing. - TaskWait_EventTrigger_DoesNothing - making OnTrigger honour the event leaves it green, because the awaited task reaches the same final state either way. The name claims more than the body checks (D2). - UniTaskWait_EventTrigger_DoesNothing - shares OnTrigger with the above; the two overloads are not separately guarded, which is itself worth recording. - SplitActivity_CompleteOnlyOneActivity_OnHold needed the inverse mutation to the one first tried: dropping the inner term from IsCompleted does nothing because Complete() has already set the surviving term. RCR: SimpleTest (Wait) <- WaitState.cs OnTrigger return null instead of the completion-gated transition RCR: SplitActivity_CompleteBoth_Success <- WaitActivity.cs AreInnerCompleted if (true) RCR: SplitActivity_CompleteOnlyOneActivity_OnHold <- WaitActivity.cs AreInnerCompleted if (false) RCR: WaitState_EventTrigger_ForceCompleted <- WaitState.cs OnTrigger suppress the targeted-event return RCR: WaitState_EventTriggerWithoutTarget_OnlyEvokesOnTransition <- WaitState.cs OnTrigger suppress the targetless-event return RCR: WaitState_MissingConfiguration_ThrowsException <- (none; double-guarded) RCR: WaitState_MissingTarget_ThrowsException <- WaitState.cs Validate TargetState guard to if (false) RCR: WaitState_TransitionsLoop_ThrowsException <- WaitState.cs Validate self-target guard to if (false) RCR: SimpleTest (TaskWait) <- TaskWaitState.cs OnTrigger return null instead of the completion-gated transition RCR: TaskWait_EventTrigger_DoesNothing <- (none; D2 review candidate) RCR: UniTaskWait_EventTrigger_DoesNothing <- (none; shares OnTrigger with the above) RCR: TaskWait_MissingConfiguration_ThrowsException <- (none; double-guarded) RCR: TaskWait_MissingTarget_ThrowsException <- TaskWaitState.cs Validate TargetState guard to if (false) RCR: TaskWait_TransitionsLoop_ThrowsException <- TaskWaitState.cs Validate self-target guard to if (false) 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>
… exemption TaskWait_EventTrigger_DoesNothing was a D2 overclaim: it triggered the event and then unblocked the task, so both "the event advanced it" and "the task did" reached the same final state and no assertion could separate them. Moved the discriminating assertions into the window after Trigger and before the unblock, where an honoured event would show up. TaskWaitState.OnTrigger returning _transition on a non-null event now reddens it in isolation (verified). State_TriggerNotConfiguredEvent_NoEffect was mislabelled A3. SimpleState.OnTrigger and its _events map do participate, so the behaviour is this package's - it is simply double-guarded. Reclassified as UNFALSIFIABLE with the sanctioned wording, and both halves were actually observed green rather than asserted: - StatechartEvent.GetHashCode => 0 : still misses, Equals rejects in the bucket - StatechartEvent.Equals => always true : never consulted, differing hash probes another bucket Also picks up the section 2 fourth verdict class (A3 reject -> delete), applied verbatim across all six Tests/AGENTS.md. RCR: TaskWait_EventTrigger_DoesNothing <- TaskWaitState.cs OnTrigger return _transition when statechartEvent != null 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>
All 8 mutations applied, observed red, reverted; both production files verified byte-identical afterwards. The two layer-guard tests are separated arithmetically rather than by disabling the guard: LeaveState.Validate requires `TargetState.RegionLayer == RegionLayer - 1`, so mutating the constant to `RegionLayer` admits the same-layer target (reddening only the same-layer test) and mutating it to `RegionLayer - 2` admits the two-layer jump (reddening only the wrong-layer test). Each leaves the other green, so the two halves of one guard are pinned independently rather than collapsing into one claim. The same split applies to the missing-configuration vs missing-target pair on the null-conditional guard above it. The three behavioural tests share the leave mechanism and redden together; that overlap is recorded on each rather than papered over. RCR: SimpleNestTest <- LeaveState.cs Enter fan-out loop bound i < 0 RCR: SimpleSplitTest <- SplitState.cs ProcessInnerStates leaveState.LeaveTransition to _transition RCR: SplitState_OnlyLeaveInnerStates_LeaveFirstState <- SplitState.cs ProcessInnerStates disable the is LeaveState capture RCR: LeaveState_MissingConfiguration_ThrowsException <- LeaveState.cs Validate guard to LeaveTransition != null && ... RCR: LeaveState_MissingTarget_ThrowsException <- LeaveState.cs Validate guard to LeaveTransition == null RCR: LeaveState_MultipleTransitions_ThrowsException <- LeaveState.cs Transition duplicate guard to if (false) RCR: LeaveState_SameLayerTarget_ThrowsException <- LeaveState.cs Validate layer check RegionLayer - 1 to RegionLayer RCR: LeaveState_WrongLayerTarget_ThrowsException <- LeaveState.cs Validate layer check RegionLayer - 1 to RegionLayer - 2 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Mutations were mapped by probe rather than guessed: seven candidate one-line edits were applied in turn and the resulting red set recorded, then each test was assigned the edit that best characterises what it uniquely pins. The ExecuteExit/ExecuteFinal flags separate cleanly in both directions, which is what makes the four force-complete variants independently falsifiable: setting a flag's guard to false reddens only the flag-on tests, ignoring the flag reddens only the flag-off tests. Each variant now carries the direction that matches its own claim. Two results worth recording: - NestedState_MissingConfiguration_ThrowsException is UNFALSIFIABLE, verified from both sides. An empty nest trips NestState.Validate's Count != 1 AND SplitState.OnValidate's Count == 0; disabling either leaves the other throwing, so neither guard alone is a valid mutation. - The four InnerEventTrigger variants (and the two MultipleNestedStates equivalents) are indistinguishable by every probed mutation. The execute flags are unreachable on that path, because the inner state is already a FinalState by the time Exit runs and the ExecuteFinal guard explicitly excludes FinalState. That makes the three Disable* variants suspected A5 duplicates of the plain CompleteSuccess test. They are annotated as suspected, not deleted - proving A5 needs evidence that NO mutation separates them, and a probe over seven candidates is not that. RCR: SimpleTest <- SplitState.cs ProcessInnerStates is-not-FinalState branch to else if (false) RCR: NestedState_WithoutTarget_Successful <- SplitState.cs Enter empty the _onEnter fan-out RCR: NestedState_InnerEventTrigger_CompleteSuccess <- SplitState.cs ProcessInnerStates inner drain loop to while (false) RCR: NestedState_InnerEventTrigger_DisableExecuteFinal_CompleteSuccess <- same (suspected A5) RCR: NestedState_InnerEventTrigger_DisableExecuteExit_CompleteSuccess <- same (suspected A5) RCR: NestedState_InnerEventTrigger_DisableExecuteExitFinal_CompleteSuccess <- same (suspected A5) RCR: NestedState_InnerEventTrigger_RunResetRun_CompleteSuccess <- SplitState.cs Enter keep CurrenState instead of rewinding to InitialState RCR: NestedState_EventTrigger_ForceCompleteSuccess <- SplitState.cs Exit ExecuteExit guard to if (false) RCR: NestedState_EventTrigger_DisableExecuteFinal_ForceCompleteSuccess <- SplitState.cs Exit ignore the ExecuteFinal flag RCR: NestedState_EventTrigger_DisableExecuteExit_ForceCompleteSuccess <- SplitState.cs Exit ignore the ExecuteExit flag RCR: NestedState_EventTrigger_DisableExecuteExitFinal_ForceCompleteSuccess <- SplitState.cs Exit ignore the ExecuteFinal flag RCR: MultipleNestedStates_InnerEventTrigger_CompleteSuccess <- SplitState.cs ProcessInnerStates inner drain loop to while (false) RCR: MultipleNestedStates_InnerEventTrigger_DisableExecuteExitFinal_CompleteSuccess <- same (suspected A5) RCR: MultipleNestedStates_EventTrigger_ForceCompleteSuccess <- SplitState.cs Exit ExecuteFinal guard to if (false && ...) RCR: MultipleNestedStates_EventTrigger__DisableExecuteExitFinal_ForceCompleteSuccess <- SplitState.cs Exit ignore the ExecuteExit flag RCR: NestedState_MissingConfiguration_ThrowsException <- (none; double-guarded, verified both sides) RCR: NestedState_TransitionsLoop_ThrowsException <- SplitState.cs OnValidate self-target check to if (false) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Tests/AGENTS.md §8 requires private fields to be _-prefixed. The local `activitySplit` variable is untouched - the convention applies to fields only. No behavioural change; EditMode green. 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>
…t 89/89 Covers StatechartSplitTest (19) and StatechartNestSplit_IntegrationTest (6). 24 of 26 mutations observed RED and reverted; all production files byte-identical afterwards. SplitState_MissingConfiguration_ThrowsException is UNFALSIFIABLE, and this time proven rather than argued: an empty split trips both SplitState.Validate's Count < 2 and SplitState.OnValidate's Count == 0, and each guard was disabled INDEPENDENTLY with the test observed staying green both times. Its sibling SplitState_SingleConfiguration splits the same guard cleanly (< 2 -> < 1) and is isolated. Deliberate avoidance worth recording: the drain-loop mutation used in the Nest slice (while (nextState != null) -> while (false)) is unusable in this filter. It prevents TaskWaitState from ever being triggered, so the awaited task never completes and three async integration tests hang for the full harness timeout rather than failing. The substitutes - Trigger(statechartEvent) -> Trigger(null), and narrowing the loop condition - leave task start-up intact. Suspected A5 duplicates, annotated not deleted: the three SplitedState_InnerEventTrigger_Disable*_CompleteSuccess variants have assertion sets identical to the plain CompleteSuccess test, because both NestedStateData flags are unreachable on the inner-event path - at SplitState.Exit the regions are already FinalState, which ExecuteFinal's own guard excludes, and ExecuteExit only reaches FinalState.Exit(), a no-op. Same shape as the NestTest finding. Proving A5 needs evidence that no mutation separates them; a candidate sweep is not that. Unpinned surface noticed in passing: SplitState.DelayForceComplete's waitState.ForceComplete() call has no test that would notice its deletion. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sections 1-2 are shared verbatim across all six packages, so this lands here even though no test in this package changed. The verdict table offered only delete-or-strengthen for a test with no unique one-line pin. That is wrong for integration tests: blast radius measures SPECIFICITY, not value. A test observed reddening under a broad mutation genuinely catches that regression even though no single line is its own. Concrete cost of the omission: mining the mutation results for A5 duplicates initially produced 56 "confirmed" candidates. Measuring blast radius cut that to 16 - the other 40 were simply tests sharing a code path, e.g. eight dying to one UiService.CloseUi mutation. Without this row they had no home and the table pointed at delete. The row carries its own abuse guard: the radius must be a recorded observation, "some mutation somewhere reddened it" is explicitly not the standard, and an over-provisioned cluster is a human editorial decision rather than an automatic verdict. 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>
§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>
Mechanical pass, no behaviour change: - dropped the empty `<param name="states"></param>` on IStateFactoryInternal.Add and the empty `<returns></returns>` on ITransitionInternal.CheckCondition — both are internal interfaces, where §6.6 bans these tags outright, and both tags carried no text - replaced the WaitActivity(Action<uint>) doc block with a `//` rationale comment; §6.6 never XML-documents constructors, and the useful part of that block was why the ctor is public on an internal type - added `/// <inheritdoc />` to StatechartEvent's Equals / GetHashCode / ToString overrides, which inherit System.Object's documentation Verified with Tools/style-audit.py: this package now reports 0 of the mechanical rule classes (A/B/C/D/K/N and documented-base overrides). 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.
Completes this package — Tools/style-audit.py reports 0 items.
The one worth reading is StatechartEvent.Equals: equality is by the
auto-incrementing Id, so two `new StatechartEvent("Jump")` instances are never
equal to each other. That is the package's most surprising behaviour (AGENTS.md
§4 calls it out) and the signature gave no hint of it.
Also documented StateInternal.OnTrigger (returns null when the state does not
handle the event), IsStateLogsEnabled, SplitState.OnValidate, the internal
LeaveState.LeaveTransition, the editor-only Statechart.CurrentState, and the
NestedStateData conversion operator.
Four of these summaries were initially written with the first line double-indented;
a repo-wide scan for doc blocks whose lines disagree on indentation now reports
only one, which predates this work.
Verified: batchmode green — EditMode 805/805, PlayMode 295/295.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`IStateMachineDebug`'s summary block indented two of its three lines with tab+space instead of tab, leaving the block internally inconsistent. Not notable enough for a CHANGELOG entry, but it was the single finding standing between the repo and a clean run of the code-standards post-edit scan — and carrying a baseline file to excuse two characters costs more than fixing them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A docs pass rewrote the file with LF, changing every historical byte and breaking the release-notes validator's baseline comparison. Restores the committed convention per AGENTS.md; no content change.
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changed: