Commit 9c41ef5269

9c41ef52694ff59e40d2bcc02780146136802f61

parent: fec160e859

Unsigned

cmc <hello@cleberg.net> · 2026-07-16 16:07 UTC

chore: record the SonarCloud + housekeeping pass, bump to 3.8.1

Update the roadmap's SonarCloud section to the live 53-issue / 10-rule
reality and mark what v3.8.1 fixed, silenced-as-bug, and left Won't Fix.
Bump MARKETING_VERSION on the app, widget, and Safari extension.

Layout: unified · split

Hutch.xcodeproj/project.pbxproj +6 −6
@@ -614,7 +614,7 @@
614 "$(inherited)", 614 "$(inherited)",
615 "@executable_path/Frameworks", 615 "@executable_path/Frameworks",
616 ); 616 );
617 MARKETING_VERSION = 3.8.0; 617 MARKETING_VERSION = 3.8.1;
618 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch; 618 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch;
619 PRODUCT_NAME = "$(TARGET_NAME)"; 619 PRODUCT_NAME = "$(TARGET_NAME)";
620 STRING_CATALOG_GENERATE_SYMBOLS = YES; 620 STRING_CATALOG_GENERATE_SYMBOLS = YES;
@@ -651,7 +651,7 @@
651 "$(inherited)", 651 "$(inherited)",
652 "@executable_path/Frameworks", 652 "@executable_path/Frameworks",
653 ); 653 );
654 MARKETING_VERSION = 3.8.0; 654 MARKETING_VERSION = 3.8.1;
655 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch; 655 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch;
656 PRODUCT_NAME = "$(TARGET_NAME)"; 656 PRODUCT_NAME = "$(TARGET_NAME)";
657 STRING_CATALOG_GENERATE_SYMBOLS = YES; 657 STRING_CATALOG_GENERATE_SYMBOLS = YES;
@@ -724,7 +724,7 @@
724 "@executable_path/Frameworks", 724 "@executable_path/Frameworks",
725 "@executable_path/../../Frameworks", 725 "@executable_path/../../Frameworks",
726 ); 726 );
727 MARKETING_VERSION = 3.8.0; 727 MARKETING_VERSION = 3.8.1;
728 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch.HutchWidgetExtension; 728 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch.HutchWidgetExtension;
729 PRODUCT_NAME = "$(TARGET_NAME)"; 729 PRODUCT_NAME = "$(TARGET_NAME)";
730 SKIP_INSTALL = YES; 730 SKIP_INSTALL = YES;
@@ -753,7 +753,7 @@
753 "@executable_path/Frameworks", 753 "@executable_path/Frameworks",
754 "@executable_path/../../Frameworks", 754 "@executable_path/../../Frameworks",
755 ); 755 );
756 MARKETING_VERSION = 3.8.0; 756 MARKETING_VERSION = 3.8.1;
757 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch.HutchWidgetExtension; 757 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch.HutchWidgetExtension;
758 PRODUCT_NAME = "$(TARGET_NAME)"; 758 PRODUCT_NAME = "$(TARGET_NAME)";
759 SKIP_INSTALL = YES; 759 SKIP_INSTALL = YES;
@@ -782,7 +782,7 @@
782 "@executable_path/Frameworks", 782 "@executable_path/Frameworks",
783 "@executable_path/../../Frameworks", 783 "@executable_path/../../Frameworks",
784 ); 784 );
785 MARKETING_VERSION = 3.8.0; 785 MARKETING_VERSION = 3.8.1;
786 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch.HutchSafariExtension; 786 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch.HutchSafariExtension;
787 PRODUCT_NAME = "$(TARGET_NAME)"; 787 PRODUCT_NAME = "$(TARGET_NAME)";
788 SKIP_INSTALL = YES; 788 SKIP_INSTALL = YES;
@@ -811,7 +811,7 @@
811 "@executable_path/Frameworks", 811 "@executable_path/Frameworks",
812 "@executable_path/../../Frameworks", 812 "@executable_path/../../Frameworks",
813 ); 813 );
814 MARKETING_VERSION = 3.8.0; 814 MARKETING_VERSION = 3.8.1;
815 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch.HutchSafariExtension; 815 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch.HutchSafariExtension;
816 PRODUCT_NAME = "$(TARGET_NAME)"; 816 PRODUCT_NAME = "$(TARGET_NAME)";
817 SKIP_INSTALL = YES; 817 SKIP_INSTALL = YES;
ROADMAP.md +58 −24
@@ -198,23 +198,54 @@ Labels and hints appear in 17 of 89 view files. Mechanical and low-risk, but it
198cannot be verified from a build — it needs VoiceOver driven on a device. 198cannot be verified from a build — it needs VoiceOver driven on a device.
199Independent of every other bucket, so it can move if a device pass is convenient. 199Independent of every other bucket, so it can move if a device pass is convenient.
200 200
201### SonarCloud backlog — v3.8.1 201### SonarCloud backlog — done in code (v3.8.1)
202 202
20351 open issues: **0 bugs, 0 vulnerabilities, 51 code smells**, plus 3 security 203The live count is **53 issues / 10 rules**, not the 51 / 5 an earlier pass
204hotspots. The headline number is misleading, so trust the breakdown before 204recorded — a reminder that this section rots like everything else, so query the
205budgeting: 205API before budgeting. **0 bugs, 0 vulnerabilities**; everything is a code smell
206 206or hotspot. What the code side of v3.8.1 actually did:
207- **35× `swift:S1075` (hardcoded URI)** — 28 of them in 207
208 `SourceHutWebDeepLinkMapperTests`, 5 in `Shared/HutchDeepLinkURLs`. A deep-link 208Fixed (`e93972f`):
209 mapper's tests exist precisely to assert against literal URLs, and a client for 209
210 one forge has fixed endpoints by definition. These want triaging as *Won't 210- **`swift:S1871`** — `RootView` had byte-identical `.home` / `.recentActivity`
211 Fix* in SonarCloud, not refactoring. "Fixing" them would make the code worse. 211 deep-link cases. Merged; recent activity is a *section* of Home, not a screen,
212- **5× `swift:S1135`** — TODO comments. Two are in `HutchIntents` and name real 212 so both correctly land on the Home tab.
213 gaps. 213- **3× `swift:S1186` (empty closure/function, CRITICAL)** — two are
214- **3× `swift:S1186` (empty closure)** — all three CRITICAL, all three trivial: 214 `Button("Cancel", role: .cancel) {}` (dialog dismissal needs no body); the
215 `Button("Cancel", role: .cancel) {}` needs no body. A comment settles it. 215 third is an empty `URLProtocol.stopLoading()` override in a test. All three now
216- **2× `javascript:S4624`** in the Safari extension; **2× `swift:S1172`** unused 216 carry a nested comment. Note the earlier claim that "all three are Cancel
217 parameters. 217 buttons" was wrong — only two are.
218- **`swift:S108`** — the expected-miss `catch` in `APICacheTests` is commented.
219- **`swift:S1172`** — the unused `url` in `mimeType(for:)` is now `_`.
220- **2× `javascript:S4624`** — the nested template literal in the deep-link
221 builders (`background.js`, `content.js`) is extracted to a `pathSegment` var.
222
223Fixed as a real bug instead (`65412ee`), not silenced:
224
225- **2× `swift:S1172` on `forceRefresh`** — `HomeViewModel.loadProjects` and
226 `loadSystemStatusSnapshot` took the flag and dropped it, so dashboard
227 pull-to-refresh returned cached projects and status. This is the trap named at
228 the top of this file. `ProjectsListView` carried the same defect via its own
229 `.refreshable`. Both fixed at the root in `ProjectService.fetchProjects`.
230
231Won't Fix, with reasons (resolve in SonarCloud's web UI, not in code):
232
233- **35× `swift:S1075` (hardcoded URI)** — 28 in `SourceHutWebDeepLinkMapperTests`,
234 the rest in `HutchDeepLinkURLs`. A deep-link mapper's tests exist to assert
235 literal URLs, and a one-forge client has fixed endpoints. "Fixing" them makes
236 the code worse.
237- **`swift:S107`** — `executeCached` has 8 params across **38 call sites**. A
238 param object would rewrite the hottest networking method for no behaviour or
239 correctness gain against an arbitrary 7-param line. Not worth the regression
240 surface.
241- **`swift:S1481`** — `ArtifactsView`'s `@Bindable var vm` is flagged unused, but
242 `$vm.error` is used at line 134; Sonar's Swift analyzer misses the projected
243 value. False positive — removing it breaks the build.
244- **`javascript:S7785`** — prefers top-level `await` for `injectBannerIfEnabled()`,
245 but `content.js` is a classic content script, not a module. Top-level `await`
246 would be a syntax error. Not applicable.
247- **5× `swift:S1135`** — TODO comments (INFO). Two in `HutchIntents` name real
248 gaps; leave them until those features land.
218 249
219The 3 hotspots are the part actually worth thought: 250The 3 hotspots are the part actually worth thought:
220 251
@@ -234,10 +265,11 @@ The 3 hotspots are the part actually worth thought:
234Query it with: 265Query it with:
235`https://sonarcloud.io/api/issues/search?componentKeys=zerolabsco_hutch&resolved=false` 266`https://sonarcloud.io/api/issues/search?componentKeys=zerolabsco_hutch&resolved=false`
236 267
237This is a patch because nothing executes differently afterwards. The 35 hardcoded-URI 268This was scoped as a patch on the assumption nothing executes differently — and
238issues are resolved as *Won't Fix* in SonarCloud's web UI — not a commit at all — and 269that mostly held: the cosmetic fixes are comments, a merge, and a rename. The one
239the rest is three comments and one annotation. If it produces a diff that changes a 270exception earns the release its own line: the `forceRefresh` fix changes what
240runtime path, something has gone wrong. 271pull-to-refresh does, so it needs a manual pass on a device before v3.8.1 ships,
272not just a green suite.
241 273
242### Ingest "What's cooking on SourceHut?" — v3.9.0 274### Ingest "What's cooking on SourceHut?" — v3.9.0
243 275
@@ -309,7 +341,9 @@ which already consults the persistent cache before the memory layer.
309Like Swift 6 above, this is internal and rides along with whatever release 341Like Swift 6 above, this is internal and rides along with whatever release
310already touches that area. Neither justifies a tag. 342already touches that area. Neither justifies a tag.
311 343
312## Housekeeping — v3.8.1 344## Housekeeping
313 345
314- `Hutch/Hutch/App/AccountSession.swift` sits in a stray nested directory; 346- ~~`Hutch/Hutch/App/AccountSession.swift` sits in a stray nested directory;
315 `Hutch/HutchTests/` is empty. 347 `Hutch/HutchTests/` is empty.~~ Done (v3.8.1, `9834b78`). Moved beside the rest
348 of `App/`; both stray dirs removed. No pbxproj change — the target is a
349 synchronized root group, so the file compiled by path all along.