--- name: audit-build-warnings description: Build the Bitwarden iOS app, capture all compiler and lint warnings, categorize them into Swift 6 concurrency vs actionable, and interactively fix the actionable ones. Use when asked to "audit build warnings", "fix warnings", "clean up warnings", "build warnings", or to reduce compiler noise before a PR. allowed-tools: - AskUserQuestion - Bash(grep:*) - Bash(mkdir:*) - Bash(mint run swiftformat:*) - Bash(mint run swiftlint:*) - Bash(mint run xcodegen:*) - Bash(rm .claude/tmp/bitwarden_build_output.txt) - Bash(rm .claude/tmp/build_warnings_report.md) - Bash(Scripts/audit-build-warnings-prep.sh) - Bash(xcodebuild:*) - Edit - Grep - Read - Write --- # Audit Build Warnings ## Setup Determine the build scheme from the user's phrasing; default to `Bitwarden` if none specified. Generate the Xcode project for the selected scheme (`.xcodeproj` files are gitignored): | Scheme | Description | Spec | |--------|-------------|------| | `Bitwarden` *(default)* | Password Manager | `project-pm.yml` | | `Authenticator` | Authenticator | `project-bwa.yml` | | `BitwardenKit` | BitwardenKit | `project-bwk.yml` | | `TestHarness` | Test Harness | `project-bwth.yml` | ```bash mint run xcodegen --spec ``` Read simulator config — always read these files, never hardcode values: ```bash DEVICE=$(tr -d '\n' < .test-simulator-device-name) OS=$(tr -d '\n' < .test-simulator-ios-version) ``` ## Phase 1: Pre-process (auto-fix before building) Run all deterministic auto-fixers *before* the build so their warnings never appear in the report. ```bash Scripts/audit-build-warnings-prep.sh ``` The script prints an `=== autofix-summary ===` block at the end. Read those counts — they appear in the Phase 4 report, but the individual changes are **not** listed as actionable warnings since they're already fixed. ## Phase 2: Build & Capture Run the build for testing and capture all output to a temp file: ```bash mkdir -p .claude/tmp xcodebuild build-for-testing \ -workspace Bitwarden.xcworkspace \ -scheme \ -destination "platform=iOS Simulator,name=$DEVICE,OS=$OS" \ -configuration Debug \ 2>&1 | tee .claude/tmp/bitwarden_build_output.txt ``` Confirm the build result (`** BUILD SUCCEEDED **` vs `** BUILD FAILED **`). If it failed, report errors and stop — don't proceed to warning fixes. Extract unique warnings (exclude timestamp lines starting with the year): ```bash grep -E "warning:" .claude/tmp/bitwarden_build_output.txt \ | grep -v "^20[0-9][0-9]" \ | sort -u ``` ## Phase 3: Categorize Classify every warning into one of these buckets: ### 🔴 Swift 6 Concurrency (always skip — tracked separately) Keywords that identify these: `Sendable`, `non-Sendable`, `actor-isolated`, `nonisolated`, `@preconcurrency`, `main actor`, `Sendable closure`, `sendable closure`, `data races`, `Swift 6 language mode` ### 🟡 Actionable (candidates for fixing) Everything else, sub-divided by fix type: - **SwiftLint** — `file_length`, `line_length`, `orphaned_doc_comment`, and any other warnings not resolved by Phase 1 - **Swift compiler** — deprecation warnings, always-true/always-false casts, protocol near-matches - **Retroactive conformance** — `extension declares a conformance of imported type … to imported protocol` ### ⚪ Default Skips (propose to user unless they override) These categories are typically intentional or in third-party code — default to skipping them: - **Vendored / third-party code**: any file under paths like `BitwardenWatchShared/MessagePack/`, `**/Vendor/`, or other vendored directories - **Deprecated API warnings** where the replacement requires non-trivial SDK changes (flag these for the user to decide) - **Always-true / always-false casts** (`'as' test is always true`) — may be intentional defensive guards - **Protocol near-match** warnings in third-party code ## Phase 4: Report Write a temporary markdown report to `.claude/tmp/build_warnings_report.md` (gitignored — do NOT write to `Docs/` or any other tracked directory). Structure: 1. **Pre-fix summary**: files touched by SwiftFormat and SwiftLint `--fix` in Phase 1 2. **Summary table**: count per category 3. **Swift 6 Concurrency section**: list all warnings grouped by sub-theme (actor isolation, Sendable captures, etc.) — presented for awareness, not fixing 4. **Actionable section**: list all remaining warnings grouped by type (SwiftLint, compiler, retroactive conformance) 5. **Default skips section**: list warnings proposed to skip with rationale 6. **Fix feasibility notes**: auto-fixable vs manual vs complex Present the summary table to the user inline (don't make them open the file). ## Phase 5: Confirm Exclusions Ask the user one question: > "Here are the **[N] actionable warnings** I found. By default I'll skip: [list default-skip items]. > Which additional warnings (if any) would you like to exclude before I fix the rest?" Accept free-form input, or "none" / "proceed as-is". Record the final exclusion list. ## Phase 6: Fix Apply fixes for each remaining actionable warning not in the exclusion list, one file at a time: - **Superfluous `// swiftlint:disable`**: delete the disable comment line - **Unused closure parameter**: replace the named parameter with `_` - **Line length violation** in a comment: break the comment line; maintain indentation/continuation markers - **Line length violation** in a function signature: break to multi-line. **Always add a trailing comma on the last parameter** when doing so — Swift 6.2 + `trailingCommas` rule require it - **file_length violation**: add `// swiftlint:disable file_length` as the **very first line** of the file, before any imports or doc comments. Do NOT place it between a doc comment and its declaration (this would trigger `orphaned_doc_comment`) - **Retroactive conformance** (`extension declares a conformance of imported type X to imported protocol Y`): add `@retroactive` before the protocol name in the extension conformance list ### Verify after manual fixes Run a targeted SwiftLint + SwiftFormat lint check on only the files that were changed: ```bash mint run swiftlint lint ... | grep -E "warning:|error:" mint run swiftformat --lint --lenient ... ``` If new violations appear, fix them before proceeding. ## Phase 7: Summary & Cleanup 1. Present a final summary: - How many warnings were auto-fixed in Phase 1 (SwiftFormat + SwiftLint `--fix`) - How many warnings were manually fixed (by type) - Which warnings were intentionally skipped (and why) - How many Swift 6 concurrency warnings remain (with a note that these require a dedicated effort) 2. Suggest next steps: - Commit the fixes using `bitwarden-delivery-tools:committing-changes` - If there are 10+ Swift 6 warnings, suggest creating a PM ticket to track them 3. Ask the user whether to delete the temp artifacts (both are gitignored under `.claude/tmp/`, so there is no repo-hygiene obligation — the user may want to re-inspect them): - `.claude/tmp/build_warnings_report.md` - `.claude/tmp/bitwarden_build_output.txt` Only run the `rm` commands if the user confirms. ## Guard Rails **Never fix Swift 6 concurrency warnings** in this workflow — they require actor annotations, `@preconcurrency` imports, or protocol-level changes that need intentional review, not automated fixing. **Never modify `BitwardenSdk` types directly** — they come from the Rust SDK. Use `@retroactive` conformances instead. **Stop and surface** any warning that would require changing a public API, moving a file between modules, or touching the Bitwarden SDK — these need human review before fixing.