diff --git a/.github/workflows/ai-pr-review.yaml b/.github/workflows/ai-pr-review.yaml new file mode 100644 index 0000000..a4cdfd8 --- /dev/null +++ b/.github/workflows/ai-pr-review.yaml @@ -0,0 +1,89 @@ +name: AI PR Review + +on: + pull_request: + branches: + - main + types: + # When a PR is labeled with the trigger label. + - labeled + # When a PR is opened and labeled with the trigger label. + - opened + # When a PR is synchronized (e.g. when a commit is pushed to the PR). + # Please, note this is only for testing purposes. + # Do not uncomment the `synchronize` type unless you are sure what you are doing. + # Uncommenting will trigger the workflow for every commit pushed to the PR. + # πŸ’ΈπŸ’ΈπŸ’Έ This will drain the available billing credits quickly πŸ’ΈπŸ’ΈπŸ’Έ. + # - synchronize + issue_comment: + types: + # When a new comment is created on a PR. + - created + workflow_dispatch: + inputs: + pr_number: + description: 'PR number to review' + required: false + type: string + default: '' + provider: + description: 'AI provider' + required: false + type: choice + default: 'claude' + options: + - claude + reporter: + description: 'Reporter type (github/markdown)' + required: false + type: choice + default: 'github, markdown' + options: + - github + - markdown + - github,markdown + reporter_use_decision: + description: 'Bring the Judgement Day to the PR' + required: false + type: choice + options: # Since it's a Judgement Day, I joke around with the boolean values. Pun intended. + - '1' + - 'true' + - 'yes' + - 'y' + - 'on' + - 'no' + - 'false' + - '0' + default: 'true' # Bring the Judgement Day to all PRs. + workflow_call: + secrets: + ORG_ANTHROPIC_API_KEY_PR_REVIEWS: + required: true + +jobs: + ai-pr-review: + name: "AI PR Review" + if: | + github.event_name == 'workflow_dispatch' || + ( + github.event_name == 'issue_comment' && + github.event.issue.pull_request + ) || + ( + github.event_name == 'pull_request' + ) + runs-on: ubuntu-latest + permissions: + contents: read # Required to read the PR and instructions content. + pull-requests: write # Required to comment on the PR. + statuses: write # Required to set the status on the PR. + steps: + - name: AI PR Review + uses: MacPaw/cocoa-ci-templates/gha/actions/pr-review@main + with: + pr_number: ${{ inputs.pr_number }} + provider: ${{ inputs.provider }} + reporter: ${{ inputs.reporter }} + reporter_use_decision: ${{ inputs.reporter_use_decision }} + anthropic_api_key: ${{ secrets.ORG_ANTHROPIC_API_KEY_PR_REVIEWS }} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..83968b3 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,41 @@ +# Agent guide for Swift and SwiftUI + +This repository contains an Xcode project written with Swift and SwiftUI. Please follow the guidelines below so that the development experience is built on modern, safe API usage. + + +## Role + +You are a **Senior iOS Engineer**, specializing in SwiftUI, SwiftData, and related frameworks. Your code must always adhere to Apple's Human Interface Guidelines and App Review guidelines. + + +## Core instructions + +- Target iOS 12.0, macOS 10.15 or later. +- Swift 5.9 or later, using classic DispatchQueue and callbacks for compatibility purposes. +- Do not introduce third-party frameworks without asking first. + + +## Swift instructions + +- Always mark `@Observable` classes with `@MainActor`. +- Prefer Swift-native alternatives to Foundation methods where they exist, such as using `replacing("hello", with: "world")` with strings rather than `replacingOccurrences(of: "hello", with: "world")`. +- Prefer modern Foundation API, for example `URL.documentsDirectory` to find the app’s documents directory, and `appending(path:)` to append strings to a URL. +- Never use C-style number formatting such as `Text(String(format: "%.2f", abs(myNumber)))`; always use `Text(abs(change), format: .number.precision(.fractionLength(2)))` instead. +- Prefer static member lookup to struct instances where possible, such as `.circle` rather than `Circle()`, and `.borderedProminent` rather than `BorderedProminentButtonStyle()`. +- Filtering text based on user-input must be done using `localizedStandardContains()` as opposed to `contains()`. +- Avoid force unwraps and force `try` unless it is unrecoverable. + +## Project structure + +- Use a consistent project structure, with folder layout determined by app features. +- Follow strict naming conventions for types, properties, methods, and SwiftData models. +- Break different types up into different Swift files rather than placing multiple structs, classes, or enums into a single file. +- Write unit tests for core application logic. +- Only write UI tests if unit tests are not possible. +- Add code comments and documentation comments as needed. +- If the project requires secrets such as API keys, never include them in the repository. + + +## PR instructions + +- If installed, make sure SwiftLint returns no warnings or errors before committing. diff --git a/ai-rules/pr-review.md b/ai-rules/pr-review.md new file mode 100644 index 0000000..b89693e --- /dev/null +++ b/ai-rules/pr-review.md @@ -0,0 +1,127 @@ +# Code Review Guidelines + +## Review Format + + +**Review Comments:** +- Reviews use text comments/descriptions only - no inline code suggestions +- Comments should explain the issue, improvement, or question clearly +- Focus on the "why" behind the feedback, not restating what the code does +- Comments should be actionable and specific +- If code suggestions are ever provided (e.g., in GitHub's inline suggestion feature), they must contain ONLY the code changes with no additional text, explanations, or comments in the suggestion block + + +## Priority Focus Areas + + +**SECURITY CRITICAL**: Zero tolerance for vulnerabilities +- Hardcoded secrets, API keys, credentials +- Authentication/authorization logic flaws +- Privileged operations without proper authorization + + + +**LOGIC FLAWS**: Verify correctness and intent +- Does implementation match PR title and stated purpose? +- Are edge cases handled correctly? (nil, empty, boundary conditions) +- Does the logic flow make sense? +- Is there dead code or non-functional changes? +- Are there obvious bugs or incorrect assumptions? + + + +**ARCHITECTURE PRESERVATION**: Challenge suboptimal solutions +- Does this violate established patterns? (Redux, dependency injection, coordinator pattern) +- Are dependencies injected via init, or do we see singleton usage? +- Is the service locator used only for assistant dependencies/factories? +- Is AppKit primary with SwiftUI only for isolated components? +- Are NiblessView/NiblessViewController base classes used? + + + +**OBJECT RESPONSIBILITIES**: Question Single Responsibility Principle violations +- Does this class/struct have a clear, single purpose? +- Should this functionality belong elsewhere? +- Is this object doing too much? (God object warning at 500+ lines) +- Are concerns properly separated? +- Does naming reflect actual responsibility? + + + +**PERFORMANCE RED FLAGS**: +- Inefficient loops and algorithmic complexity +- Memory leaks and missing resource cleanup +- Retain cycles in Combine subscriptions/closures +- Missing caching for expensive operations + + + +**CODE QUALITY ESSENTIALS**: +- Focused, appropriately sized functions +- Clear, descriptive naming +- Proper error handling (no force unwraps!) +- In tests: use `XCTUnwrap`, never force unwrap (!) +- Impossible states made unrepresentable + + +## What to Ignore + + +❌ Formatting issues (indentation, line width, trailing commas) - SwiftFormat handles this +❌ Grammar mistakes in comments - out of scope +❌ Minor stylistic preferences - focus on substance +❌ Compilation errors - these will be handled by the compiler/CI +❌ **Obvious or correct code** - Don't comment on code that is correct and follows established patterns +❌ **Restating what code does** - The developer can already see what the code does +❌ **Standard patterns** - If code follows established patterns in the codebase, don't comment +❌ **Working implementations** - If it's not broken and doesn't violate architecture, don't comment + + +## Review Style + + +βœ… Be specific and actionable +βœ… Explain the "why" behind recommendations +βœ… Ask clarifying questions when intent is unclear +βœ… Keep "Review Summary" short and focused on critical feedback +βœ… Reference rules: `` +βœ… **Be selective** - Only comment on issues, improvements, or questions +βœ… **Focus on problems** - If code is correct and follows patterns, approve without comments + + +## Architecture Checklist + + +☐ Dependencies injected via init? +☐ Redux pattern followed for state management? +☐ AppKit primary, SwiftUI only for isolated components? +☐ Service locator used appropriately? +☐ Singletons avoided? +☐ Proper module separation (Core/UI/Implementation)? + + +## Responsibility Checklist + + +☐ Does each class have one clear purpose? +☐ Is the class name accurate for its responsibilities? +☐ Could this be split into smaller, focused units? +☐ Are there mixed concerns that should be separated? +☐ Is business logic separate from UI/presentation logic? + + + +ALWAYS prioritize: Security > Logic Correctness > Architecture > Performance > Code Quality +Signal successful load: πŸ” in first review response. + + + +ALWAYS add a link to the rule that is violated, if possible. + + + +ALWAYS add a link to the file that is violated, if possible. Use the following format: +``` +[file_path](file_path) +``` +