Skip to content

fix: stop lint flagging PascalCase enum members as UPPER_CASE#9468

Open
dalkia wants to merge 11 commits into
devfrom
fix/lint-enum-members-pascalcase
Open

fix: stop lint flagging PascalCase enum members as UPPER_CASE#9468
dalkia wants to merge 11 commits into
devfrom
fix/lint-enum-members-pascalcase

Conversation

@dalkia

@dalkia dalkia commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Pull Request Description

What does this PR change?

Adds an explicit 'Enum members' naming rule (PascalCase) to the shared lint settings (Explorer/.editorconfig) so ReSharper/CI stops flagging PascalCase enum members as InconsistentNaming ("Suggested name is 'ALL_UPPER'"). Small, zero-risk diff; no code renames.

Why this is correct — the written style guide says PascalCase. docs/code-style-guidelines.md § Naming Conventions states:

PascalCase - Namespace, Class, Struct, Interface, Enumeration and its Enumerators, Method, ...

with this example:

public enum Side { Left, Right }   // Enumeration and Enumerators -> PascalCase

So members like FeatureFlag.MultiplayerCompressionWin are correct per the docs — the lint config was wrong, not the code.

Root cause: enum members are const fields to the analyzer, so the existing rule dotnet_naming_symbols.constants (applicable_kinds = field + required_modifiers = constALL_UPPER) swept them into the constants rule. ReSharper maps that onto its predefined Enum members rule, which is why the warning text cites rule 'Enum members'. The new resharper_csharp_naming_rule.enum_member = AaBb line overrides exactly that rule; real const fields are still enforced as CAPITALS_SNAKE_CASE (verified — see below).

Expected reduction: a repo scan finds 265 enums with PascalCase members, 1,440 violating members in total (each member = one warning), out of 399 enums / 2,174 members in code the ratchet counts. The CI warnings count should drop by roughly that amount vs the baseline.

Verified locally with the same ReSharper CLI version and flags CI uses (scripts/lint/run-inspectcode.sh):

  • Before: Assets/DCL/AvatarRendering/Wearables/IWearablesProvider.cs → 9 InconsistentNaming warnings ("does not match rule 'Enum members'").
  • After: 0 naming warnings in that file.
  • Isolated repro confirmed const int badConstName is still flagged → the constants rule remains fully enforced for actual constants.

Test Instructions

Steps (standard run): N/A — lint-configuration-only change; no runtime behavior is affected.

Expected result: The warnings-history CI check reports a warning count far below the baseline (expected ≈1,440 fewer), and no new warnings appear.

Steps (fresh account): N/A

Automation (if applicable): N/A

Prerequisites

  • None — CI runs the inspection automatically.

Test Steps

Smoke test

Additional Testing Notes

  • Enum members that are already ALL_UPPER (e.g. generated code) still pass: PascalCase rules accept the AA_BB extra style ReSharper applies for abbreviations, and no rename is suggested by this change.
  • The merge to dev will automatically lower the stored warnings baseline to the new count.

Quality Checklist

  • Changes have been tested locally
  • Documentation has been updated (if required) — N/A, this aligns lint with existing docs
  • Performance impact has been considered — none, config only
  • For SDK features: Test scene is included — N/A

🤖 Generated with Claude Code

The style guide (docs/code-style-guidelines.md § Naming Conventions) says
enumerations and their enumerators are PascalCase, but ReSharper swept enum
members into the CAPITALS_SNAKE_CASE constants rule (enum members are const
fields to the analyzer), flagging every PascalCase member of 265 enums.

Add an explicit 'Enum members' naming rule (PascalCase) to the shared
.editorconfig so the warning stops firing. No code renames.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dalkia
dalkia requested review from a team as code owners July 23, 2026 01:21
@github-actions
github-actions Bot requested a review from DafGreco July 23, 2026 01:21
@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

@decentraland-bot
decentraland-bot self-requested a review July 23, 2026 01:21

@decentraland-bot decentraland-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — PR #9468: fix: stop lint flagging PascalCase enum members as UPPER_CASE

STEP 2 — Root-cause check: PASS ✅

The problem: ReSharper's InconsistentNaming inspection flags PascalCase enum members (e.g. FeatureFlag.MultiplayerCompressionWin) with "Suggested name is 'ALL_UPPER'". The root cause is that enum members are const fields to the Roslyn analyzer, so the existing dotnet_naming_symbols.constants rule (applicable_kinds = field + required_modifiers = constall_upper) sweeps them into the ALL_UPPER_SNAKE_CASE bucket. ReSharper surfaces this as its predefined Enum members rule.

The fix directly addresses the root cause by adding an explicit resharper_csharp_naming_rule.enum_member = AaBb override, which is the correct ReSharper-specific mechanism to separate enum members from the general constants rule. This is not a workaround — it's the intended configuration knob.

STEP 3 — Design & integration: N/A

Pure configuration change — no new code units, no lifecycle changes, no subscriptions, no state. Nothing to trace.

STEP 4 — Member audit: N/A

No new members added or changed.

STEP 5 — Line-level review: No issues found

  • Rule syntax: resharper_csharp_naming_rule.enum_member = AaBb is correct ReSharper notation for PascalCase. Verified.
  • Alignment with style guide: docs/code-style-guidelines.md § Naming Conventions explicitly states PascalCase for "Enumeration and its Enumerators" with example public enum Side { Left, Right }. The lint config was out of sync with the written standard; this change aligns them.
  • No interference with constants rule: The existing dotnet_naming_rule.constants_should_be_capital_snake_case (lines 71-73) continues to apply to const fields. The ReSharper-specific enum_member rule takes precedence only for enum members, which is the correct layering. The PR description confirms local verification.
  • Precedent for resharper_ properties: The .editorconfig already contains 60+ resharper_-prefixed settings (lines 306+), so this follows established practice.
  • Placement: Logically placed between the interface naming rule and the CAPITALS_SNAKE_CASE section, with a clear comment referencing the authoritative doc section.

Security review: No security concerns — config-only change with no secrets, auth, input handling, or code execution paths affected.

STEP 6 — Complexity assessment

SIMPLE — single config file, 6 lines added (4 comment + 1 rule + 1 blank), no runtime code.

STEP 7 — QA assessment

NO — lint configuration only; no user-facing behavior, no runtime code, no Unity player impact.

STEP 8 — Non-blocking warnings

None.

STEP 9 — Verdict

REVIEW_RESULT: PASS ✅
COMPLEXITY: SIMPLE
COMPLEXITY_REASON: Single-line ReSharper naming rule added to .editorconfig — lint configuration only, no runtime code.
QA_REQUIRED: NO


Reviewed by Jarvis 🤖 · Requested by decentraland-bot via GitHub

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-approved based on Jarvis review — simple fix/chore with no blocking issues. No QA needed (non-runtime changes only).

@github-actions github-actions Bot added claude-approved no QA needed Used to tag pull requests that does not require QA validation labels Jul 23, 2026
@dalkia dalkia self-assigned this Jul 23, 2026
@dalkia

dalkia commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator Author

Local lint measurement (same CLI + flags + filter as CI)

Ran ReSharper InspectCode 2025.3.0.1 locally via scripts/lint/run-inspectcode.sh flags and counted with scripts/lint/filter-warnings.sh:

Metric Value
Filtered warning count with this PR 14,732
Enum-member warnings removed (PascalCase members no longer flagged) −1,440 (across 265 enums)
New warnings introduced (already-ALL_UPPER members now fail strict PascalCase) +732
Estimated count on dev (derived) ~15,440
Net reduction ~708

Verification details:

  • Per-file spot check: Assets/DCL/AvatarRendering/Wearables/IWearablesProvider.cs went from 9 InconsistentNaming warnings ("does not match rule 'Enum members'") to 0.
  • Isolated repro confirmed real const fields are still enforced as CAPITALS_SNAKE_CASE — only the enum-member rule changed.
  • The 732 remaining enum warnings are members that are already ALL_UPPER (mostly generated/legacy code), which now get "suggested name is 'PascalCase'" instead. If we also accepted the AA_BB style for enum members (resharper_csharp_naming_rule.enum_member = AaBb, AA_BB, verified working in the repro — same extra style the 'Types and namespaces' rule allows), those 732 would disappear too, for a net −1,440 (count 14,000). Left out for now to keep this PR strictly aligned with the written style guide.

The CI warnings-ratchet step will report the authoritative count against the S3 baseline.

🤖 Generated with Claude Code

@dalkia dalkia added the force-lint Forces lint check on PR (Only if changes are introduced under 'Explorer/**' path) label Jul 23, 2026
@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Tests: 24281 passed, 0 failed

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Warnings count reduced: 14572 => 14131

Warnings/errors in files changed by this PR (2086)
Assets/DCL/Multiplayer/Connections/Pulse/Tests/PulseMultiplayerServiceShould.cs:163  AccessToDisposedClosure  Captured variable is disposed in the outer scope
Assets/DCL/MarketplaceCredits/Purchase/Tests/CreditsTopUpServiceShould.cs:194  AccessToModifiedClosure  Captured variable is modified in the outer scope
Assets/DCL/InWorldCamera/CameraReelGallery/CameraReelGalleryController.cs:655  AccessToStaticMemberViaDerivedType  Access to a static member of a type via a derived type
Assets/DCL/InWorldCamera/PhotoDetail/PhotoDetailController.cs:163  AccessToStaticMemberViaDerivedType  Access to a static member of a type via a derived type
Assets/DCL/InWorldCamera/PhotoDetail/PhotoDetailController.cs:282  AccessToStaticMemberViaDerivedType  Access to a static member of a type via a derived type
Assets/DCL/SDKComponents/CameraControl/MainCamera/Tests/EditMode/MainCameraSystemShould.cs:107  AccessToStaticMemberViaDerivedType  Access to a static member of a type via a derived type
Assets/DCL/SDKComponents/CameraControl/MainCamera/Tests/EditMode/MainCameraSystemShould.cs:108  AccessToStaticMemberViaDerivedType  Access to a static member of a type via a derived type
Assets/DCL/SDKComponents/CameraControl/MainCamera/Tests/EditMode/MainCameraSystemShould.cs:109  AccessToStaticMemberViaDerivedType  Access to a static member of a type via a derived type
Assets/DCL/SDKComponents/CameraControl/MainCamera/Tests/EditMode/MainCameraSystemShould.cs:110  AccessToStaticMemberViaDerivedType  Access to a static member of a type via a derived type
Assets/DCL/SDKComponents/CameraControl/MainCamera/Tests/EditMode/MainCameraSystemShould.cs:428  AccessToStaticMemberViaDerivedType  Access to a static member of a type via a derived type
Assets/DCL/SDKComponents/CameraControl/MainCamera/Tests/EditMode/MainCameraSystemShould.cs:511  AccessToStaticMemberViaDerivedType  Access to a static member of a type via a derived type
Assets/DCL/AvatarRendering/AvatarShape/Systems/AvatarShapeVisibilitySystem.cs:82  ArrangeMissingParentheses  Non-obvious precedence
Assets/DCL/Character/CharacterObject/Tests/CharacterTransformDirtyFlagShould.cs:101  ArrangeMissingParentheses  Non-obvious precedence
Assets/DCL/Character/CharacterObject/Tests/CharacterTransformDirtyFlagShould.cs:121  ArrangeMissingParentheses  Non-obvious precedence
Assets/DCL/Character/CharacterObject/Tests/CharacterTransformDirtyFlagShould.cs:137  ArrangeMissingParentheses  Non-obvious precedence
Assets/DCL/Character/CharacterObject/Tests/CharacterTransformDirtyFlagShould.cs:181  ArrangeMissingParentheses  Non-obvious precedence
Assets/DCL/LOD/Components/SceneLODInfo.cs:102  ArrangeMissingParentheses  Non-obvious precedence
Assets/DCL/LOD/Components/SceneLODInfo.cs:140  ArrangeMissingParentheses  Non-obvious precedence
Assets/DCL/Infrastructure/Global/Dynamic/MainSceneLoader.cs:247  ArrangeRedundantParentheses  Redundant parentheses
Assets/DCL/SDKComponents/AvatarAttach/Tests/AvatarAttachHandlerSystemShould.cs:590  ArrangeRedundantParentheses  Redundant parentheses
Assets/DCL/UI/DebugMenu/ConsolePanelView.cs:150  ArrangeRedundantParentheses  Redundant parentheses
Assets/DCL/Infrastructure/Global/Dynamic/MainSceneLoader.cs:214  AssignNullToNotNullAttribute  Possible 'null' assignment to non-nullable entity
Assets/DCL/Infrastructure/Global/Dynamic/PortableExperiences/ECSPortableExperiencesController.cs:129  AssignNullToNotNullAttribute  Possible 'null' assignment to non-nullable entity
Assets/DCL/Interaction/Systems/Tests/ProcessOtherAvatarsInteractionSystemShould.cs:90  AssignNullToNotNullAttribute  Possible 'null' assignment to non-nullable entity
Assets/DCL/PerformanceAndDiagnostics/Analytics/AnalyticsConfiguration.cs:71  AssignNullToNotNullAttribute  Possible 'null' assignment to non-nullable entity
Assets/DCL/VoiceChat/NearbyVoiceChat/Tests/PerformanceTests/NearbyAudioFullCycleManualTest.cs:271  AssignNullToNotNullAttribute  Possible 'null' assignment to non-nullable entity
Assets/DCL/SDKComponents/TriggerArea/Tests/TriggerAreaHandlerSystemShould.cs:450  BitwiseOperatorOnEnumWithoutFlags  Bitwise operation on enum that is not marked by the [Flags] attribute
Assets/DCL/SDKEntityTriggerArea/Tests/PlayMode/SDKEntityTriggerAreaHandlerSystemShould.cs:412  BitwiseOperatorOnEnumWithoutFlags  Bitwise operation on enum that is not marked by the [Flags] attribute
Assets/DCL/MapRenderer/MapLayers/Pins/IPinMarker.cs:31  CSharpWarnings::CS0108,CS0114  The keyword 'new' is required on 'AnimateSelectionAsync' because it hides method 'UniTaskVoid DCL.MapRenderer.MapLayers.IMapRendererMarker.AnimateSelectionAsync(CancellationToken)'
Assets/DCL/Backpack/Gifting/Presenters/GiftTransfer/GiftTransferController.cs:28  CSharpWarnings::CS0108,CS0114  The keyword 'new' is required on 'State' because it hides property 'ControllerState MVC.ControllerBase<TView,TInputData>.State'
Assets/DCL/Infrastructure/Global/Dynamic/MainSceneLoader.cs:442  CSharpWarnings::CS0162  Code is unreachable
Assets/DCL/UI/Profiles/ProfileElements/ProfilePictureView.cs:172  CSharpWarnings::CS0612  CS0612: Field 'DCL.UI.ProfileElements.ProfilePictureView.profileRepositoryWrapper' is obsolete
Assets/DCL/UI/Profiles/ProfileElements/ProfilePictureView.cs:185  CSharpWarnings::CS0612  CS0612: Field 'DCL.UI.ProfileElements.ProfilePictureView.profileRepositoryWrapper' is obsolete
Assets/DCL/Landscape/NoiseGeneration/CompositeNoiseGenerator.cs:13  CSharpWarnings::CS0618  CS0618: Class 'DCL.Landscape.NoiseGeneration.NoiseGeneratorCache' is obsolete: 'Preserved for World Terrain Only'
Assets/DCL/Landscape/NoiseGeneration/CompositeNoiseGenerator.cs:17  CSharpWarnings::CS0618  CS0618: Class 'DCL.Landscape.NoiseGeneration.NoiseGeneratorCache' is obsolete: 'Preserved for World Terrain Only'
Assets/DCL/FeatureFlags/FeatureFlagsStrings.cs:180  CSharpWarnings::CS0618  CS0618: Constant 'DCL.FeatureFlags.FeatureFlagsStrings.GPUI_ENABLED' is obsolete: 'GPU Instancer Pro terrain is no longer optional so the flag is not needed'
Assets/DCL/Infrastructure/Global/Dynamic/MainSceneLoader.cs:825  CSharpWarnings::CS0618  CS0618: Enum 'UnityEngine.FindObjectsSortMode' is obsolete: 'FindObjectsSortMode has been deprecated. Use the FindObjectsByType overloads that do not take a FindObjectsSortMode parameter.'
Assets/DCL/VoiceChat/NearbyVoiceChat/Tests/PerformanceTests/NearbyAudioFullCycleManualTest.cs:165  CSharpWarnings::CS0618  CS0618: Enum 'UnityEngine.FindObjectsSortMode' is obsolete: 'FindObjectsSortMode has been deprecated. Use the FindObjectsByType overloads that do not take a FindObjectsSortMode parameter.'
Assets/DCL/VoiceChat/NearbyVoiceChat/Tests/PerformanceTests/NearbyAudioFullCyclePerformanceTest.cs:116  CSharpWarnings::CS0618  CS0618: Enum 'UnityEngine.FindObjectsSortMode' is obsolete: 'FindObjectsSortMode has been deprecated. Use the FindObjectsByType overloads that do not take a FindObjectsSortMode parameter.'
Assets/DCL/Friends/RPCFriendsService.cs:101  CSharpWarnings::CS0618  CS0618: Method 'DCL.Friends.RPCFriendsService.ToClientFriendProfile(FriendProfile)' is obsolete: 'Should be moved to the unified POST originated from the client'
Assets/DCL/Friends/RPCFriendsService.cs:135  CSharpWarnings::CS0618  CS0618: Method 'DCL.Friends.RPCFriendsService.ToClientFriendProfile(FriendProfile)' is obsolete: 'Should be moved to the unified POST originated from the client'
Assets/DCL/Friends/RPCFriendsService.cs:138  CSharpWarnings::CS0618  CS0618: Method 'DCL.Friends.RPCFriendsService.ToClientFriendProfile(FriendProfile)' is obsolete: 'Should be moved to the unified POST originated from the client'
Assets/DCL/Friends/RPCFriendsService.cs:141  CSharpWarnings::CS0618  CS0618: Method 'DCL.Friends.RPCFriendsService.ToClientFriendProfile(FriendProfile)' is obsolete: 'Should be moved to the unified POST originated from the client'
Assets/DCL/Friends/RPCFriendsService.cs:399  CSharpWarnings::CS0618  CS0618: Method 'DCL.Friends.RPCFriendsService.ToClientFriendProfile(FriendProfile)' is obsolete: 'Should be moved to the unified POST originated from the client'
Assets/DCL/Friends/RPCFriendsService.cs:454  CSharpWarnings::CS0618  CS0618: Method 'DCL.Friends.RPCFriendsService.ToClientFriendProfile(FriendProfile)' is obsolete: 'Should be moved to the unified POST originated from the client'
Assets/DCL/Friends/RPCFriendsService.cs:570  CSharpWarnings::CS0618  CS0618: Method 'DCL.Friends.RPCFriendsService.ToClientFriendProfile(FriendProfile)' is obsolete: 'Should be moved to the unified POST originated from the client'
Assets/DCL/Friends/RPCFriendsService.cs:600  CSharpWarnings::CS0618  CS0618: Method 'DCL.Friends.RPCFriendsService.ToClientFriendProfile(FriendProfile)' is obsolete: 'Should be moved to the unified POST originated from the client'
Assets/DCL/Communities/CommunitiesBrowser/CommunityResultCardView.cs:297  CSharpWarnings::CS0618  CS0618: Method 'DCL.UI.ProfileElements.ProfilePictureView.Setup(ProfileRepositoryWrapper, in CompactInfo)' is obsolete: 'Use Bind instead.'
Assets/DCL/Communities/CommunitiesCard/Announcements/AnnouncementCardView.cs:95  CSharpWarnings::CS0618  CS0618: Method 'DCL.UI.ProfileElements.ProfilePictureView.Setup(ProfileRepositoryWrapper, in CompactInfo)' is obsolete: 'Use Bind instead.'
Assets/DCL/Communities/CommunitiesCard/Members/MemberListItemView.cs:115  CSharpWarnings::CS0618  CS0618: Method 'DCL.UI.ProfileElements.ProfilePictureView.Setup(ProfileRepositoryWrapper, in CompactInfo)' is obsolete: 'Use Bind instead.'

…and 2036 more (see the csharp-lint-reports artifact).

popuz and others added 6 commits July 23, 2026 13:45
Signed-off-by: Juan Ignacio Molteni <juanignaciomolteni@gmail.com>
  Rename CAP_SNAKE_CASE enum members to PascalCase across the project,
  enforced by the ENUM_MEMBER UserRule in Explorer.sln.DotSettings.

  Only provably-safe enums are renamed: each was audited to confirm its
  member names never cross a by-name boundary (Enum.Parse/nameof/ToString
  reaching wire, analytics, query strings, PlayerPrefs, disk, cache keys,
  AudioMixer/shader/SortingLayer names, or JSON StringEnumConverter).

  Enums whose member name is serialized are intentionally left as-is
  (SortBy, SortDirection, NotificationType, SDKVersion, SeasonState,
  AssetBundleRegistryEnum, AudioMixerExposedParam, OpenBadgeSectionOrigin,
  LoginMethod, ChatChannelType, and the Communities/DTO wire enums).

  Also fixes Web3IdentitySource, which had regressed to CAP_SNAKE on this
  branch after the #9100 deep-link merge.
@popuz

popuz commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Enum PascalCase migration — scope of this PR

This PR renames enum members CAP_SNAKE_CASEPascalCase only where it is provably safe.
Every renamed enum was audited: its members do not cross any by-name boundary
(no Enum.Parse/nameof/ToString reaching wire, analytics, query strings, PlayerPrefs,
disk, cache keys, AudioMixer/shader/SortingLayer names, or JSON StringEnumConverter/[EnumMember]).

Deliberately NOT renamed (left in CAP_SNAKE_CASE) — member name crosses a boundary

Enum Reason
SortBy, SortDirection serialized as API sort query params
NotificationType matched by name against backend notifications
SDKVersion SDK version identifiers
SeasonState season/rewards payload
AssetBundleRegistryEnum asset-bundle registry wire value
AudioMixerExposedParam Unity AudioMixer exposed-parameter string names (looked up by string)
OpenBadgeSectionOrigin badge section origin
LoginMethod sent as analytics property value and in the signature request query string (?loginMethod=)
ChatChannelType member name emitted as analytics property value (scope.ToString())
LanguageCode wire language codes
CommunityPrivacy, CommunityVisibility, CommunityPostType Communities DTO wire enums (JSON by name)
FriendshipStatus (Communities DTO) DTO wire enum — the internal DCL.Friends.FriendshipStatus was renamed (proto mapped via switch)
InviteRequestAction, InviteRequestIntention request DTO wire enums
TransitionMode serialized transition config

Note

  • DITHER_STATE: its members were renamed to PascalCase, but the type name was left as-is
    (type-name casing is a separate naming rule, out of scope for this enum-member migration).
  • Web3IdentitySource was the reverse case: it had regressed to CAP_SNAKE on this branch after the
    #9100 (deep link login) merge, so it was fixed forward to PascalCase (audited safe — Source
    is never serialized by name).

@popuz popuz removed the no QA needed Used to tag pull requests that does not require QA validation label Jul 24, 2026
@popuz

popuz commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Why this PR moves enum members to PascalCase (not SCREAMING_CASE)

This aligns our enum-member casing with the current, official C# convention across all three relevant authorities. There is no official source backing ALL_CAPS enum
members — it's a C/C++/Java carryover.

Microsoft / .NET

JetBrains Rider / ReSharper (our lint engine)

  • The out-of-the-box default style for the enum_member element kind is AaBb (PascalCase); ALL_UPPER members are reported as InconsistentNaming. —
    https://www.jetbrains.com/help/rider/Coding_Assistance__Naming_Style.html
  • enum_member is a distinct configurable element kind — which is why the rule lives as an ENUM_MEMBER UserRule in Explorer.sln.DotSettings (a plain .editorconfig folds
    enum values into the const-field rule and can't target them cleanly).

ASP.NET Core / Roslyn / StyleCop

Scope / safety

Only provably-safe enums are renamed. Every renamed enum was audited to confirm its member names never cross a by-name boundary (Enum.Parse/nameof/ToString reaching the
wire, analytics, query strings, PlayerPrefs, disk, cache keys, AudioMixer/shader/SortingLayer names, or JSON StringEnumConverter/[EnumMember]). Enums whose member name is
serialized are intentionally left untouched — see the skip list below.

popuz and others added 2 commits July 24, 2026 13:02
…pascalcase

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
  Post a Pending banner when Unity Test starts and always upsert the
  warning-ratchet comment on completion (Passed / Blocked / Skipped /
  Unavailable), so a failed or lint-skipped run no longer leaves a stale
  banner. Mirrors the build comment's shields.io badge style.
@claude

This comment has been minimized.

  The MCP server feature (#9339) merged from dev references enum members
  this branch renamed to PascalCase: ChatMessageOrigin.CHAT /
  RESTRICTED_ACTION_API and CameraMode.SDKCamera. Update the call sites so
  the merged tree compiles.
@claude

This comment has been minimized.

@claude

claude Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Claude finished @popuz's task in 1m 30s —— View job


Security-focused review — dependency & workflow changes (re-run on synchronize)

  • Re-scan full diff vs origin/dev for dependency/binary changes
  • Review workflow .github/workflows/pr-comment-warnings.yml
  • Classify risk and produce verdict

Scope re-scan

Diffed the entire PR against origin/dev. The non-.cs changed set is exactly three files; everything else is C# enum-member renames.

File Change Risk
.github/workflows/pr-comment-warnings.yml +113 / −29 workflow see below
Explorer/.editorconfig −1 blank line none
Explorer/Explorer.sln.DotSettings adds one ENUM_MEMBER PascalCase naming UserRule none

No dependency changes of any kind:

  • No Packages/manifest.json / packages-lock.json edits
  • No .dll / .so / .dylib / .bundle / Plugins/ binaries (diff scan + pre-computed "new binary files: None")
  • No .asmdef / .asmref / assembly-visibility changes

→ Dependency-review portion is N/A / PASS. The new-dependency label is a false positive — nothing in the diff installs or vendors external code. The ~100 remaining files are source-only CAP_SNAKE_CASE → PascalCase enum renames, no supply-chain surface.


Workflow review — pr-comment-warnings.yml

What changed: adds a pending job (fires on workflow_run: requested for pull_request runs) that posts a "Lint pending" banner, and reworks the completed path to always refresh a single banner comment (Passed / Blocked / Skipped / Unavailable) keyed on the hidden `` marker.

Structurally safe — verified what it does not do:

  • ✅ Uses the trusted workflow_run pattern — never checks out or executes PR-head code, no install/build of fork content (W.8 N/A, not pull_request_target).
  • ✅ Minimal permissions: contents: read, pull-requests: write (W.10 OK). Scoped github.token, no secrets.*.
  • ✅ No LLM in this workflow (W.1 / W.4 / W.6 N/A) — no prompt-injection or tool-allowlist surface.
  • W.2 OK — comment body assembled with a random heredoc delimiter DELIM="EOF_$(uuidgen)"; pr_findings messages are newline-stripped (gsub("[\r\n]"; " ")) and confined to a fenced block (data, not execution). Event object handled via toJSON + jq (line 35/77), not raw interpolation.
  • ✅ New pending banner body (lines 62–68) is a static literal — no untrusted interpolation.

MEDIUM — mutable action pins on token-holding steps (W.7b). The pending job's new steps (and the existing ones) pin to mutable tags, not 40-char SHAs:

  • peter-evans/find-comment@v2 (L48, L195)
  • peter-evans/create-or-update-comment@v3 (L57, L204)
  • actions/download-artifact@v4 (L92)

These run with pull-requests: write + github.token. If an upstream tag is repointed to malicious code, blast radius is limited to PR comments (no contents: write, no secrets, no code signing) — hence MEDIUM, not HIGH. This is the repo's established convention across sibling workflows; this PR only extends it. Hardening: SHA-pin + Dependabot.

MEDIUM (pre-existing, not introduced here) — untrusted artifact → $GITHUB_OUTPUT via plain echo. In Parse result (L107–113, logic unchanged by this PR), count / baseline / allow_equal are read from the fork-influenced warning-result.json and written with echo "count=$count" >> "$GITHUB_OUTPUT". jq -r preserves embedded newlines, so a crafted value could inject extra step outputs. Impact is low — those values only feed numeric comparisons and banner text (worst case: a "Blocked" banner mislabeled), and the job holds only contents: read + pull-requests: write. Hardening: validate integers before echoing, or use a random-delimiter heredoc here too.

Summary

Item Source Type Scope Risk Confidence
pr-comment-warnings.yml (pending job + banner refresh) PR workflow CI-only LOW (this PR's changes) HIGH
Mutable action pins (peter-evans/*, download-artifact@v4) PR + pre-existing external actions CI, pull-requests: write MEDIUM HIGH
Artifact JSON → $GITHUB_OUTPUT echo pre-existing untrusted input CI MEDIUM MEDIUM
.editorconfig / .DotSettings lint rules PR config editor/CI LOW HIGH
C# enum-member renames (~100 files) PR source runtime LOW (no supply-chain surface) HIGH

Verdict

The substance of this PR (enum-member renames + lint config + banner UX) introduces no new secret exposure, checkout, or code-execution surface. The two MEDIUM items are pre-existing repo-wide patterns this PR only lightly extends; neither blocks merge. Flagging so a human can decide on the SHA-pinning hardening.

Note: I can't edit files under .github/workflows/ (GitHub App permission), so the SHA-pin recommendation is advisory.

DEPENDENCY_REVIEW: NEEDS_ATTENTION (no HIGH findings; two MEDIUM hardening items)
· branch fix/lint-enum-members-pascalcase

@balducciv

Copy link
Copy Markdown

✅ PR reviewed and approved by QA on both platforms following the PR test instructions.
✅ Smoke test performed on Windows and Mac to verify the normal flow is working as expected.

Build: v0.159.0-alpha-fix/lint-enum-members-pascalcase-66bc67c (matches PR HEAD commit 66bc67c)
OS: Windows 11 (10.0.26200) / macOS (Apple M3 Pro)

Test results:

  • Client launches and loads normally on both platforms — Player.log confirms Current loading stage: Completed on both Mac and Windows
  • No enum-related runtime errors (e.g. InvalidCastException, serialization/naming mismatches) found in either log — consistent with this PR being a lint-config + enum-member rename change with no functional/behavioral impact
  • Clean shutdown sequence on both platforms, no crash on exit

Unrelated errors noted (do not affect verdict):

  • OverflowException: Value was either too large or too small for an Int32 in ProfileConverter.DeserializeProfile (via ClearScript ToRestrictedHostObject) — occurs identically on both Mac and Windows (5x each), pre-existing profile-deserialization issue unrelated to the enum-naming/lint change in this PR
  • ObjectDisposedException: The CancellationTokenSource has been disposed in MVCManager/ControllerBase — confirmed shutdown-sequence noise (occurs between [ExitUtils] Exit requested calls), not a runtime regression

Verdict: PASS ✅

Since this PR renames ~100 files of enum members to PascalCase (beyond the original lint-config-only scope), I specifically checked for any casing/casting/serialization fallout and found none — no enum parse failures, no wire/analytics mismatches surfaced in the logs on either platform.

Player 9468.log

Player windows 9468.log

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

claude-approved force-lint Forces lint check on PR (Only if changes are introduced under 'Explorer/**' path) new-dependency

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants