Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions .github/workflows/ai-pr-review.yaml
Original file line number Diff line number Diff line change
@@ -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'
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default value for the reporter parameter contains a space in "github, markdown", which may not work as expected if the underlying action expects comma-separated values without spaces. Consider changing to "github,markdown" without the space to match the format in the options list.

Suggested change
default: 'github, markdown'
default: 'github,markdown'

Copilot uses AI. Check for mistakes.
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'
Comment on lines +49 to +57
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment states this is a "Judgement Day" joke with boolean values, but the choices include string values like 'true', 'yes', 'y', 'on', 'no', 'false', '0', '1' which is confusing and error-prone. Consider simplifying to just 'true' and 'false' for clarity and to avoid potential parsing issues in the downstream action.

Suggested change
options: # Since it's a Judgement Day, I joke around with the boolean values. Pun intended.
- '1'
- 'true'
- 'yes'
- 'y'
- 'on'
- 'no'
- 'false'
- '0'
options: # Since it's a Judgement Day, I still joke, but keep canonical boolean values.
- 'true'
- 'false'

Copilot uses AI. Check for mistakes.
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 }}
41 changes: 41 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -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.
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The minimum iOS version specified as iOS 12.0 is outdated and may not support modern Swift features mentioned in the document. iOS 12.0 was released in 2018 and doesn't support many modern Swift and SwiftUI features. Consider updating to at least iOS 15.0 or iOS 16.0 to properly support Swift 5.9 features, SwiftUI, and the modern Foundation APIs mentioned elsewhere in this guide.

Suggested change
- Target iOS 12.0, macOS 10.15 or later.
- Target iOS 16.0, macOS 13.0 or later.

Copilot uses AI. Check for mistakes.
- Swift 5.9 or later, using classic DispatchQueue and callbacks for compatibility purposes.
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The instruction to use "classic DispatchQueue and callbacks for compatibility purposes" contradicts the requirement for Swift 5.9 or later and modern APIs. Swift 5.9 has full support for async/await and structured concurrency, which are superior to callbacks for maintainability and avoiding callback hell. This guidance may lead developers to write outdated code patterns when modern concurrency is available.

Suggested change
- Swift 5.9 or later, using classic DispatchQueue and callbacks for compatibility purposes.
- Swift 5.9 or later; prefer async/await and structured concurrency, using DispatchQueue and callbacks only when interoperating with legacy APIs.

Copilot uses AI. Check for mistakes.
- 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.
127 changes: 127 additions & 0 deletions ai-rules/pr-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# Code Review Guidelines

## Review Format

<required>
**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
</required>

## Priority Focus Areas

<rule_1 priority="HIGHEST">
**SECURITY CRITICAL**: Zero tolerance for vulnerabilities
- Hardcoded secrets, API keys, credentials
- Authentication/authorization logic flaws
- Privileged operations without proper authorization
</rule_1>

<rule_2 priority="HIGHEST">
**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?
</rule_2>

<rule_3 priority="HIGH">
**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?
</rule_3>

<rule_4 priority="HIGH">
**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?
</rule_4>

<rule_5 priority="MEDIUM">
**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
</rule_5>

<rule_6 priority="MEDIUM">
**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
</rule_6>

## What to Ignore

<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
</ignore>

## Review Style

<review_approach>
✅ 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: `<!-- rule:@ai-rules/pr-review.md#rule-1 -->`
✅ **Be selective** - Only comment on issues, improvements, or questions
✅ **Focus on problems** - If code is correct and follows patterns, approve without comments
</review_approach>

## Architecture Checklist

<architecture_verification>
☐ 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)?
</architecture_verification>

## Responsibility Checklist

<responsibility_verification>
☐ 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?
</responsibility_verification>

<meta_instruction>
ALWAYS prioritize: Security > Logic Correctness > Architecture > Performance > Code Quality
Signal successful load: 🔍 in first review response.
</meta_instruction>

<required>
ALWAYS add a link to the rule that is violated, if possible.
</required>

<required>
ALWAYS add a link to the file that is violated, if possible. Use the following format:
```
[file_path](file_path)
```
</required>
Loading