Skip to content

chore: exclude CheckNamespace from the lint warning ratchet#9396

Merged
dalkia merged 10 commits into
devfrom
chore/exclude-checknamespace-ci
Jul 17, 2026
Merged

chore: exclude CheckNamespace from the lint warning ratchet#9396
dalkia merged 10 commits into
devfrom
chore/exclude-checknamespace-ci

Conversation

@dalkia

@dalkia dalkia commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Pull Request Description

What does this PR change?

Replaces #9373 with a narrower approach: instead of disabling the CheckNamespace inspection everywhere via .editorconfig, it is excluded in scripts/lint/filter-warnings.sh — the filter shared by the CI warning ratchet and the local AI-flow lint hook — so both count warnings identically. IDE inspection (Rider) is untouched and still highlights mismatches.

Rationale: namespaces in this codebase are domain names, not folder paths (e.g. DCL.Ipfs lives in the DCL.Network assembly), so folder-namespace mismatch is expected and should not consume the warning ratchet — CheckNamespace accounts for 4,444 of the 19,087 warnings in the current dev baseline (~23%).

Changes:

  • scripts/lint/filter-warnings.sh: CheckNamespace added to the built-in ruleId exclusions, next to .CSharpErrors/.CppCompilerErrors.
  • CLAUDE.md, docs/code-style-guidelines.md, .claude/skills/code-standards/SKILL.md: codify that suppressing the inspection with // ReSharper disable once CheckNamespace is forbidden — the lint filter already ignores the inspection, so the comment is pure noise, and it hides genuine cases where a type joined the wrong namespace. Full rule lives in the style guide; the other two files carry one-line pointers.

Verified against the actual InspectCode report from the latest dev run (29508710993): the filtered count drops from 19,087 to 14,643 — exactly the 4,444 CheckNamespace results — and no other rule is affected.

Note for the merge to dev: the warning count will drop by ~4,444, which the ratchet reads as a reduction, and the baseline re-seeds on the dev push — no no-warning-ratchet label needed.

Test Instructions

CI-only change — nothing to run in the client.

Expected result: the Count warnings step of the test.yml lint job on this PR reports ~14,643 instead of ~19,087, and jq '[.[] | select(.ruleId == "CheckNamespace")] | length' filtered.json on the inspect-code-reports artifact returns 0.

Quality Checklist

  • Changes have been tested locally
  • Documentation has been updated (if required)
  • Performance impact has been considered
  • For SDK features: Test scene is included

🤖 Generated with Claude Code

Namespaces are domain names, not folder paths, so folder-namespace
mismatch is expected in this codebase. Drop CheckNamespace from the
remote warning count via an opt-in EXCLUDE_RULES filter, while local
inspection (Rider and the AI-flow Stop hook) keeps reporting it.
Codify in the conventions docs that suppressing it with a ReSharper
comment is forbidden.

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

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

@decentraland-bot
decentraland-bot self-requested a review July 16, 2026 16:54
@dalkia dalkia self-assigned this Jul 16, 2026
@decentraland-bot

Copy link
Copy Markdown
Contributor

Sorry, I encountered an error processing your review request. The team has been notified.

@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.

PR Review: chore: exclude CheckNamespace from the CI warning ratchet only

STEP 2 — Root-cause check: PASS

The problem is clear: CheckNamespace accounts for 4,444 of 19,087 CI warnings (~23%), but namespaces in this codebase are domain names that deliberately don't match folder paths (e.g. DCL.Ipfs in the DCL.Network assembly). The diff addresses the cause — excluding the irrelevant inspection from the CI ratchet — rather than disabling it everywhere or suppressing individual occurrences. Local inspection remains untouched.

STEP 3 — Design & integration: PASS

No new long-lived units, systems, or lifecycle management. This is a CI script enhancement with a clean, extensible design:

  • EXCLUDE_RULES env var — optional, comma-separated, defaults to empty (no exclusion). Backward compatible: every existing caller of filter-warnings.sh is unchanged.
  • Opt-in is scoped — only .github/actions/count-warnings/action.yml sets EXCLUDE_RULES=CheckNamespace at the step level, so the local AI-flow lint hook (lint-changed.sh) continues reporting CheckNamespace.
  • jq parameterization--arg excluded "${EXCLUDE_RULES:-}" is safe (no injection risk, no code evaluation). The split(",") | map(select(length > 0)) correctly handles empty strings, trailing commas, and the zero-rules default. IN($skip[]) returns false for an empty stream, so all rules pass through when unset. Verified.

STEP 4 — Member audit: N/A

No public properties, accessors, or code members added — CI scripts and documentation only.

STEP 5 — Line-level review: No issues found

Pass A (blocking issues):

  • Shell script uses set -euo pipefail, proper double-quoting of ${EXCLUDE_RULES:-}, and safe jq --arg parameterization. No injection vectors.
  • The (.ruleId // "") fallback handles results without a ruleId safely (falls through to empty string, never matches the skip list since map(select(length > 0)) removes empties).
  • Documentation updates across CLAUDE.md, docs/code-style-guidelines.md, and .claude/skills/code-standards/SKILL.md are consistent and accurate.

Pass B (design/encapsulation smells): Nothing applicable — no runtime code, no classes, no state.

Security review: Clean

  • EXCLUDE_RULES is hardcoded in the action YAML, not sourced from untrusted PR input.
  • jq --arg treats the value as a string literal, not executable code.
  • No secrets, credentials, or internal URLs exposed.
  • IN($skip[]) uses exact string equality — no regex/wildcard bypass possible.

Git conventions (ADR-6): PASS

  • PR title: chore: exclude CheckNamespace from the CI warning ratchet only — correct semantic commit format.
  • Branch name: chore/exclude-checknamespace-ci — correct <type>/<summary> pattern.

STEP 8 — Non-blocking warnings: None

Main scene not modified. No warnings.


REVIEW_RESULT: PASS ✅
COMPLEXITY: SIMPLE
COMPLEXITY_REASON: CI shell script filter and documentation updates only — no runtime, ECS, or Unity code touched.
QA_REQUIRED: NO


Reviewed by Jarvis 🤖 · Requested by Juan Ignacio Molteni [Dalkia] (<@U07FBNXHWKN>) via Slack

github-actions[bot]
github-actions Bot previously approved these changes Jul 16, 2026

@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 16, 2026
@dalkia dalkia added the force-lint Forces lint check on PR (Only if changes are introduced under 'Explorer/**' path) label Jul 16, 2026
…inters elsewhere

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dalkia dalkia added force-lint Forces lint check on PR (Only if changes are introduced under 'Explorer/**' path) and removed force-lint Forces lint check on PR (Only if changes are introduced under 'Explorer/**' path) labels Jul 16, 2026
@dalkia
dalkia marked this pull request as draft July 16, 2026 17:43
@dalkia
dalkia marked this pull request as ready for review July 16, 2026 17:43
@decentraland-bot
decentraland-bot self-requested a review July 16, 2026 17:44

@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 #9396

chore: exclude CheckNamespace from the CI warning ratchet only


STEP 2 — Root-cause check: PASS

Problem: CheckNamespace accounts for ~4,444 of the ~19,087 warnings in the current dev baseline (~23%). Namespaces in this codebase are domain names, not folder paths (e.g. DCL.Ipfs lives in the DCL.Network assembly), so folder-namespace mismatches are intentional and expected — they should not consume the warning ratchet.

Fix: Excludes CheckNamespace from the CI ratchet's count only, leaving local inspection (Rider, AI-flow Stop hook) intact. This is the right approach — it addresses the root cause (noise in the ratchet) rather than suppressing the inspection everywhere.

STEP 3 — Design & integration: PASS

No new long-lived units are introduced — this is a CI/tooling change. The design is clean:

  • Generic mechanism (EXCLUDE_RULES env var) added to the existing filter-warnings.sh rather than hardcoding a special case. The env-var approach is appropriate: it keeps the script caller-agnostic and composable.
  • Backward-compatible default: empty/unset EXCLUDE_RULES excludes nothing, so the local AI-flow hook (lint-changed.sh) and any other callers are completely unaffected.
  • Single opt-in point: only the CI action (count-warnings/action.yml) sets the env var.
  • Documentation is updated consistently across three locations (CLAUDE.md anti-patterns, docs/code-style-guidelines.md § Namespaces, .claude/skills/code-standards/SKILL.md), each at the appropriate level of detail with cross-references.

No lifecycle owners to search — no runtime units affected.

STEP 4 — Member audit: N/A

No public properties, accessors, or methods introduced.

STEP 5 — Line-level review: No issues found

Shell script (filter-warnings.sh):

  • --arg excluded "${EXCLUDE_RULES:-}" safely passes the env var as a jq string value (not as jq code). No injection risk.
  • split(",") | map(select(length > 0)) correctly handles all edge cases: empty string → [], single value, multiple values, double-commas.
  • IN($skip[]) | not is correct when $skip is empty: jq's IN(empty) returns false, | not gives true, so all items pass through. The filter becomes a no-op as intended.
  • .ruleId // "" provides a defensive fallback for results missing a ruleId field.
  • The hardcoded .CSharpErrors / .CppCompilerErrors exclusions are correctly kept separate from EXCLUDE_RULES — they are internal false-positive filters that must always apply regardless of caller context.

CI action (count-warnings/action.yml):

  • env: EXCLUDE_RULES: CheckNamespace is properly scoped to the step.
  • The explanatory comment clearly states intent and why local inspection is intentionally left unchanged.

Documentation:

  • The three locations serve different audiences (AI reviewers via CLAUDE.md, developers via code-style-guidelines.md, AI code-generation via code-standards SKILL.md) and are consistent in message: never suppress CheckNamespace with a ReSharper comment; fix the namespace or leave the warning visible.

Security review: Clean

  • EXCLUDE_RULES is interpolated into jq via --arg (safe string binding, not code injection).
  • The value is hardcoded in the CI action — not user-controlled.
  • No secrets, credentials, or sensitive data in the diff.
  • No new permissions, network access, or external dependencies.
  • set -euo pipefail is preserved for safe shell execution.

STEP 6, 7, 8

No non-blocking warnings. Main scene not modified.


REVIEW_RESULT: PASS ✅
COMPLEXITY: SIMPLE
COMPLEXITY_REASON: CI lint-filter script and documentation only — no runtime code, no ECS systems, no Unity player changes.
QA_REQUIRED: NO


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

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Warnings count reduced: 19087 => 14693

@claude

This comment has been minimized.

@claude

This comment has been minimized.

@NickKhalow NickKhalow 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.

Good addition! One comment: let's encode less meaning into the comments and more into the actual code to preserve more the single source of truth approach

Comment thread .github/actions/count-warnings/action.yml Outdated
dalkia and others added 2 commits July 17, 2026 10:29
Per review: keep local and CI consistent by excluding the rule in the
shared filter script instead of a CI-only EXCLUDE_RULES opt-in.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

This comment has been minimized.

@dalkia dalkia changed the title chore: exclude CheckNamespace from the CI warning ratchet only chore: exclude CheckNamespace from the lint warning ratchet Jul 17, 2026
@NickKhalow NickKhalow added force-lint Forces lint check on PR (Only if changes are introduced under 'Explorer/**' path) and removed force-lint Forces lint check on PR (Only if changes are introduced under 'Explorer/**' path) labels Jul 17, 2026
Per review: the excluded ruleIds and vendored-path pattern are now
named variables the jq filter consumes, with per-entry reasons inline,
so the header no longer duplicates the list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

This comment has been minimized.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Claude finished @dalkia's task in 1m 21s —— View job


Security-focused re-review (PR synchronize) — PR #9396

  • Read CLAUDE.md + review guidelines
  • Diff against origin/dev and identify what changed since the 14:19 review
  • Dependency-change scan
  • Re-confirm workflow files (test.yml, pr-comment-warnings.yml)
  • Review the new C# change (UpdateCurrentSceneSystem.cs)
  • Post verdict

What changed since the last pass

Since the 14:19 review, the only new commits are two whitespace-only "Dummy change: retrigger lint" commits (80dad62, 5b0aca7). Net effect on the tree:

  • scripts/lint/filter-warnings.sh — unchanged from the version already reviewed (data-refactor of exclusions; verified functionally equivalent).
  • .github/workflows/test.yml, .github/workflows/pr-comment-warnings.ymlbyte-identical to what was reviewed; nothing to re-litigate.
  • Explorer/.../UpdateCurrentSceneSystem.cs — one added blank line (see note below).
  • Docs / CLAUDE.md / SKILL.md — unchanged.

Dependency changes — none

No Packages/manifest.json, packages-lock.json, native/managed binaries, or .asmdef changes. No new or re-pinned GitHub Actions introduced by this PR. Supply-chain review N/A. The new-dependency label maps to nothing in this diff.

Workflow files — re-confirmed, LOW

  • test.yml → "Collect PR-file warnings": read-only (git merge-base, git diff --name-only, sed, jq over filtered.json); never checks out or executes PR code. Triggered on pull_request (not pull_request_target), so no secret exposure to forks. BASE_REF (target branch name) and HEAD_SHA are passed via env: and always quoted — neither is attacker-controllable as code. --argjson findings_total "${{ steps.pr-findings.outputs.total }}" interpolates a self-produced integer (jq length), not untrusted input. Comment posting stays deferred to the trusted workflow_run companion, so this job never holds pull-requests: write.
  • pr-comment-warnings.yml (trusted companion): heredoc still uses a static EOF delimiter on $GITHUB_OUTPUT (W.2), but every emitted message is sanitized with gsub("[|\r\n]"; " ") and every finding is a | … | table row, so no produced line can equal EOF. Residual risk LOW; a random delimiter (EOF_$(uuidgen)) remains an optional, non-blocking hardening.

Non-blocking note — stray blank line in a production file

UpdateCurrentSceneSystem.cs:24 gains an empty line purely from the "retrigger lint" dummy commits:

     public partial class UpdateCurrentSceneSystem : BaseUnityLoopSystem
     {
+
         private const string NO_DATA_STRING = "<No data>";

Not a security concern, but it's an unintended edit to runtime code that shouldn't ship with a CI-only PR — worth reverting before merge so the diff stays scoped to lint tooling + docs.

Pre-existing note (not introduced here)

pr-comment-warnings.yml still uses tag-pinned third-party actions (peter-evans/find-comment@v2, create-or-update-comment@v3, actions/download-artifact@v4) on a job holding pull-requests: write (W.7b). Untouched by this PR — worth SHA-pinning in a future hardening pass, not a blocker here.

Summary

File Type Scope Risk Confidence
filter-warnings.sh shell CI + local hook LOW HIGH
test.yml (collect step) workflow CI (PR, read-only) LOW HIGH
pr-comment-warnings.yml (heredoc) workflow CI (trusted) LOW HIGH
UpdateCurrentSceneSystem.cs (blank line) C# runtime LOW (cleanup) HIGH
docs / CLAUDE.md / SKILL.md docs LOW HIGH

No dependency changes, no dynamic code loading, no untrusted-input execution, no secret exposure, no unpinned action introduced by this PR. The workflow files are unchanged from the prior review; the only substantive new content is a stray blank line that should be reverted (functional, not security).

DEPENDENCY_REVIEW: PASS

@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.

PR Review — chore: exclude CheckNamespace from the lint warning ratchet

STEP 2 — Root-cause check: PASS

The PR correctly identifies that CheckNamespace accounts for ~23% (4,444 / 19,087) of CI warnings, and that folder-namespace mismatches are intentional in this codebase (namespaces are domain names, e.g. DCL.Ipfs in the DCL.Network assembly). Excluding the rule from the warning ratchet fixes the root cause — the ratchet was counting false positives — rather than a symptom.

STEP 3 — Design & integration: PASS

No new systems, plugins, managers, or state-holding units. All changes are CI scripts, GitHub Actions workflows, and documentation. No lifecycle, ECS, or architectural concerns apply.

STEP 4 — Member audit: N/A

No public members added or changed.

STEP 5 — Line-level review

Shell script (scripts/lint/filter-warnings.sh): The refactor from inline rule names to a declared excluded_rules array is clean and extensible. The printfjq -Rjq -s pipeline correctly builds a JSON array for --argjson. The excluded_paths regex is passed as --arg and applied with test()/IN() — correct.

Workflow (test.yml — "Collect PR-file warnings"): Properly initializes defaults before any fallible command (echo '[]' > pr-findings.json; echo "total=0"). Uses git merge-base with fallback. The sed 's#^Explorer/##' correctly aligns repo-relative paths with SARIF's project-relative paths. The ${{ steps.pr-findings.outputs.total || 0 }} expression safely defaults when the step is skipped.

Workflow (pr-comment-warnings.yml): The blocked flag and conditional <details open> are well-designed — warnings auto-expand only when they block the merge. The gsub("[|\r\n]"; " ") sanitizes pipe/newline chars to avoid breaking the markdown table.

Documentation (CLAUDE.md, style guide, skill): Consistent three-point documentation — full rule in the style guide, one-line pointers in CLAUDE.md and the skill file.

Security: No issues. Env vars (not inline ${{ }}) are used for branch names, avoiding shell injection. All ${{ }} expansions in run: blocks are integer-only (pr.number, total). No secrets exposed. jq processes InspectCode output internally — no command injection vectors.

One finding — see inline comment.

STEP 6 — Complexity: SIMPLE

CI scripts, GitHub Actions YAML, and documentation only.

STEP 7 — QA: NO

No runtime code affected. All changes are CI/tooling/docs.

STEP 8 — Non-blocking warnings

None.

STEP 9 — Verdict

REVIEW_RESULT: PASS ✅
COMPLEXITY: SIMPLE
COMPLEXITY_REASON: CI lint scripts, GitHub Actions workflows, and documentation — no runtime or ECS code.
QA_REQUIRED: NO


Reviewed by Jarvis 🤖 · Requested by Juan Ignacio Molteni [Dalkia] (<@U07RZTGR6CH>) via Slack

@github-actions
github-actions Bot dismissed their stale review July 17, 2026 14:59

Dismissed: latest Jarvis review no longer auto-approves this PR.

@github-actions

Copy link
Copy Markdown
Contributor

🔒 Jarvis reviewed this PR — sensitive paths modified (.github/prompts, .github/workflows, or CODEOWNERS). Jarvis will not auto-approve these PRs — human DEV review is required. No QA needed (Jarvis reported QA_REQUIRED: NO).

@dalkia
dalkia merged commit 05db1c0 into dev Jul 17, 2026
25 checks passed
@dalkia
dalkia deleted the chore/exclude-checknamespace-ci branch July 17, 2026 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

force-lint Forces lint check on PR (Only if changes are introduced under 'Explorer/**' path) new-dependency no QA needed Used to tag pull requests that does not require QA validation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants