ci: take SwiftLint to 2 warnings, and prove the duplicates are minutes old - #446
Merged
Conversation
…s old Two unrelated things landed together because the second blocked the first: the build broke mid-cleanup with 'CollectorOutcome is ambiguous', which is the duplicate-source failure again. SWIFTLINT: 34 -> 2 Both survivors are in files cyq's #432 touches, so they are deliberately left for that PR. `--strict` therefore still waits — but the follow-up is now "fix 2 and flip a flag" rather than "fix 33 across 15 files". Most were `swiftlint --fix`. Three needed judgment and did NOT get fixed: * SubscriptionTier's explicit "free"/"pro"/"team" raw values look redundant and are a WIRE CONTRACT — the enum is Codable and those strings are persisted and exchanged with the backend. Dropping them would bind the serialized form to the Swift case name, so a later rename silently changes stored data. Kept, with the reason at the declaration. * APIClient's `for`/`if` is not converted to `for ... where` because the condition MUTATES (`seen.insert`). A `where` clause reads as a predicate; burying an insert in one hides the side effect from anyone scanning the loop header. * `storedMaster` -> `storedLocalOnly` was safe to rename only after checking it is a local variable and no persisted key derives from it. The key is `Keys.localOnlyMode` and is untouched. Also: `swiftlint:disable:next for_where` has to sit above the `if`, not the `for` — the rule reports at the `if`. My first placement silently did nothing. DUPLICATE SOURCES: 60 more, and now we know when they arrive They appeared in a tree this guard called CLEAN twice earlier the same day. Timestamps say 07-27..08-03 in batches sharing one second exactly (26 files at 08-03 01:26:48, 22 at 12:19:59, 7 at 07-30 17:13:57) — a bulk copy, not drift. The timestamps are a lie and APFS proves it, because inodes are monotonic: CollectorRunner.swift birth 08-04 inode 250,454,865 FirstRunPresentation.swift birth 08-18 inode 261,235,600 (written that day) CollectorRunner 2.swift birth "08-03" inode 263,212,836 <-- HIGHER A duplicate claiming to predate a file by two weeks has a higher inode than it. It was written to this volume AFTERWARDS — during the 08-18 session — carrying a birth time copied from its source. So: a timestamp-preserving bulk copy into the working tree, running while a session is active. Not iCloud (no fileprovider xattr on any specimen) and not a git worktree (absent from all four). The copy reaches inside .git — `refs/heads/main 2`, which breaks `git pull` outright, and `logs/refs/heads/v1 2.15-multi-cli`, whose " 2" sits before the LAST DOT. That is macOS's own duplicate-naming algorithm. Recorded in the guard so the next investigation starts there. All 60 quarantined before deletion; the two flagged CONTENT DIFFERS were inspected first, as the guard instructs — one had zero unique lines, the other had two that assert the OPPOSITE of what the current test deliberately asserts. Nothing lost. 2696 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Two unrelated things landed together because the second blocked the first: the build broke mid-cleanup with
'CollectorOutcome' is ambiguous, which is the duplicate-source failure again.SwiftLint: 34 → 2
Both survivors are in files cyq's #432 touches, so they're deliberately left for that PR.
--strictstill waits — but the follow-up is now "fix 2 and flip a flag" rather than "fix 33 across 15 files".Most were
swiftlint --fix. Three needed judgment and did not get fixed:SubscriptionTier's explicit"free"/"pro"/"team"raw values look redundant and are a wire contract — the enum isCodableand those strings are persisted and exchanged with the backend. Dropping them would bind the serialized form to the Swift case name, so a later rename silently changes stored data. Kept, with the reason at the declaration.APIClient'sfor/ifis not converted tofor … wherebecause the condition mutates (seen.insert). Awhereclause reads as a predicate; burying an insert in one hides the side effect from anyone scanning the loop header.storedMaster→storedLocalOnlywas safe only after checking it's a local variable with no persisted key derived from it. The key isKeys.localOnlyModeand is untouched.Also worth knowing:
swiftlint:disable:next for_wheremust sit above theif, not thefor— the rule reports at theif. My first placement silently did nothing.Duplicate sources: 60 more, and now we know when they arrive
They appeared in a tree this guard called clean twice earlier the same day. Timestamps say 07-27..08-03, in batches sharing one second exactly (26 files at
08-03 01:26:48, 22 at12:19:59, 7 at07-30 17:13:57) — a bulk copy, not drift.The timestamps are a lie, and APFS proves it. Inodes are allocated monotonically:
CollectorRunner.swiftFirstRunPresentation.swift(written that day)CollectorRunner 2.swiftA duplicate claiming to predate a file by two weeks has a higher inode than it. So it was written to this volume afterwards — during the 08-18 session — carrying a birth time copied from its source.
⇒ A timestamp-preserving bulk copy into the working tree, running while a session is active.
Two things it is not, tested rather than assumed:
fileproviderxattr on any specimen (see the correction in fix: the codesign detritus was never iCloud — correcting my own attribution #444).claude/worktreesAnd the copy reaches inside
.git:refs/heads/main 2(which breaksgit pulloutright, since a space is illegal in a ref name) andlogs/refs/heads/v1 2.15-multi-cli— whose" 2"sits before the last dot, treating.15-multi-clias an extension. That is macOS's own duplicate-naming algorithm; no compiler, SwiftPM or git names a file that way.Recorded in the guard so the next investigation starts there instead of re-testing iCloud.
Verification
swift buildclean.🤖 Generated with Claude Code