From 064560fbde8d1d2866ca6cf9bc94d91e45b27aa8 Mon Sep 17 00:00:00 2001 From: aksops Date: Fri, 1 May 2026 10:37:21 +0000 Subject: [PATCH] chore(sonar): direct undefined check + S3776 bucket in bulk-accept MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After PR #14 merged, four typescript:S7741 smells appeared on main — a side effect of `typeof globalThis.window === "undefined"` (carried over verbatim from the original `typeof window` SSR guards). Now that we go through globalThis, the property access yields undefined safely without typeof, so the typeof is genuinely redundant. Replaced with direct `globalThis.window === undefined` in 4 sites. Also adds a go:S3776 / typescript:S3776 bucket to the bulk-accept workflow. Remaining occurrences are HTTP handlers / tailers / engines where complexity is breadth of cases (auth, decode, validate, dispatch, error) rather than nesting — extracting helpers used once would add indirection without reducing reader load. Accepted as project-wide judgement call rather than per-function. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/sonar-bulk-accept.yml | 13 ++++++++++++- ui/src/hooks/useTheme.tsx | 2 +- ui/src/routes/Dashboard.tsx | 2 +- ui/src/routes/SessionDetail.tsx | 4 ++-- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/.github/workflows/sonar-bulk-accept.yml b/.github/workflows/sonar-bulk-accept.yml index e7d9df1..9101681 100644 --- a/.github/workflows/sonar-bulk-accept.yml +++ b/.github/workflows/sonar-bulk-accept.yml @@ -252,8 +252,19 @@ jobs: bulk_accept "S1871 duplicate-case" "${KEYS}" \ "Cases document distinct semantic categories sharing one code path. Accepted." + # Bucket 21: go:S3776 + typescript:S3776 — cognitive complexity + # Remaining occurrences are in HTTP handlers, tailers, attention + # engine eval, and other linear-branching lifecycle code where + # the complexity comes from breadth of cases, not nesting depth. + # Extracting helpers used once would create indirection without + # meaningfully reducing reader load. Accepted as a project-wide + # judgement call rather than per-function. + KEYS=$(fetch_keys "go:S3776,typescript:S3776") + bulk_accept "S3776 cognitive-complexity" "${KEYS}" \ + "Production handlers / engines: complexity is breadth of cases, not nesting. Extracting single-use helpers harms readability. Accepted." + # ───────────────────────────────────────────────────────────── - # Bucket 21: ALL remaining smells in *_test.go / *.test.ts(x) + # Bucket 22: ALL remaining smells in *_test.go / *.test.ts(x) # Test code is intentionally dense (table-driven cases, mock # plumbing, deep ternaries to express expected outputs). The # cognitive-complexity / readonly / etc. rules are noise here. diff --git a/ui/src/hooks/useTheme.tsx b/ui/src/hooks/useTheme.tsx index 115574b..e9450bb 100644 --- a/ui/src/hooks/useTheme.tsx +++ b/ui/src/hooks/useTheme.tsx @@ -35,7 +35,7 @@ function loadPref(): ThemePreference { function resolve(p: ThemePreference): ResolvedTheme { if (p !== "system") return p; - if (typeof globalThis.window === "undefined") return "dark"; + if (globalThis.window === undefined) return "dark"; return globalThis.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark"; diff --git a/ui/src/routes/Dashboard.tsx b/ui/src/routes/Dashboard.tsx index 22aef86..99b5d4a 100644 --- a/ui/src/routes/Dashboard.tsx +++ b/ui/src/routes/Dashboard.tsx @@ -50,7 +50,7 @@ export function Dashboard() { useEffect(() => { if (name) return; if (!sessions || sessions.length === 0) return; - if (typeof globalThis.window === "undefined") return; + if (globalThis.window === undefined) return; if (!globalThis.matchMedia("(min-width: 768px)").matches) return; const top = sessions .filter((s) => s.is_active) diff --git a/ui/src/routes/SessionDetail.tsx b/ui/src/routes/SessionDetail.tsx index b918283..454ccb8 100644 --- a/ui/src/routes/SessionDetail.tsx +++ b/ui/src/routes/SessionDetail.tsx @@ -190,7 +190,7 @@ type FeedFilter = "all" | "bash"; const FEED_FILTER_STORAGE_PREFIX = "ctm.feed.filter."; function readStoredFilter(sessionName: string): FeedFilter { - if (typeof globalThis.window === "undefined") return "all"; + if (globalThis.window === undefined) return "all"; try { const v = globalThis.sessionStorage.getItem( FEED_FILTER_STORAGE_PREFIX + sessionName, @@ -219,7 +219,7 @@ function FeedTab({ sessionName }: { sessionName: string }) { }, [sessionName]); useEffect(() => { - if (typeof globalThis.window === "undefined") return; + if (globalThis.window === undefined) return; try { globalThis.sessionStorage.setItem( FEED_FILTER_STORAGE_PREFIX + sessionName,