Skip to content
Merged
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
15 changes: 15 additions & 0 deletions .agents/skills/agent-guidelines-audit/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,21 @@ For every checked-in `.xcodeproj`, read and apply the shared [Xcode project-sett
5. Before reporting a failure, search the nearest applicable `AGENTS.md` and durable project documentation linked from it for an exception naming the exact setting, scope, concrete incompatibility, replacement, impact, validation, and revisit condition. Accept and report an applicable documented exception; do not infer one from transient discussion, generic project prose, or the existing build setting itself. An application may use `INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = YES` only when that exact exception documents the shipped non-exempt cryptography and resulting export-compliance workflow.
6. When implementation is authorized, move or add compliant values at project level, remove redundant target copies, and rerun build-setting inspection plus relevant builds. For review-only work, report undocumented gaps without editing.

## Audit Swift package settings

Enumerate every checked-in `Package.swift` that belongs to repository source, ignoring `.build` and other generated build artifacts, and treat each manifest's directory as a package root. For every package, read and apply [the shared package compiler-settings baseline](../../../Guidelines/Packages.md#compiler-settings-baseline); do not infer package rules solely from the Xcode guide.

1. Identify the selected Swift/Xcode toolchain, inspect `// swift-tools-version:` and `swiftLanguageModes`, and require the newest stable language mode from the shared baseline, currently Swift 6. Reject an older effective mode unless an exact documented exception applies.
2. Run `swift package --package-path <package-root> dump-package`, or the selected-toolchain equivalent, and use the evaluated manifest to enumerate locally defined targets and their effective settings. Do not rely only on textual grep because manifests may construct or mutate settings programmatically.
3. For every locally defined target that compiles Swift and for which SwiftPM exposes `swiftSettings`, including production, test, and other applicable Swift target kinds, require unconditional `.treatAllWarnings(as: .error)` plus `ExistentialAny`, `InferIsolatedConformances`, `InternalImportsByDefault`, `MemberImportVisibility`, and `NonisolatedNonsendingByDefault` as `.enableUpcomingFeature(...)` settings. Do not require Swift settings on binary targets, system-library targets, or package plug-in targets because `Target.plugin(...)` does not expose `swiftSettings`.
4. For locally compiled C or Objective-C targets, require the applicable typed `CSetting.treatAllWarnings(as: .error)`; require the corresponding `CXXSetting` where C++ is compiled. Do not require C-family settings when those languages are absent, and do not accept `unsafeFlags` in place of available typed APIs.
5. In Swift 6 mode, treat complete strict concurrency as supplied by the language mode and require every redundant explicit `StrictConcurrency` opt-in to be removed, including `.enableUpcomingFeature("StrictConcurrency")`, `.enableExperimentalFeature("StrictConcurrency")`, and `StrictConcurrency=complete` representations found in the evaluated manifest or effective compiler arguments. Require other upcoming-feature declarations to be removed when they become unconditional in the selected language mode, especially because warnings-as-errors can promote the resulting diagnostics.
6. Do not require or automatically add `.defaultIsolation(MainActor.self)`. Its absence is compliant with the shared package baseline; source-level actor-isolation review remains a separate Swift and concurrency concern.
7. Search the nearest applicable `AGENTS.md` and linked durable documentation before reporting a package-setting failure. Accept only an exception that names the exact setting or feature, package and targets, incompatibility, replacement or omission, impact, compensating validation where applicable, and revisit condition. Do not infer an exception from the manifest.
8. Run the package's documented validation workflow and, at minimum where applicable, `swift build` and `swift test`. Warnings promoted to errors must leave both warning-clean. When conditions or helper logic make the effective invocation uncertain, use verbose SwiftPM output to verify `-warnings-as-errors`, the language mode, and every `-enable-upcoming-feature` argument.

For authorized implementation work, repair the manifest and rerun evaluated-manifest inspection plus builds. For review-only work, report the exact missing, conditional, redundant, or conflicting setting without modifying the package.

## Audit localization

When the repository contains localized targets or String Catalogs, read the shared [Localization guide](../../../Guidelines/Localization.md) and the consumer's local translation guidance:
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

All notable changes to this project are documented in this file.

## [0.0.33] - 2026-09-19

### Added

- Added a Swift Package compiler-settings baseline aligned with the applicable Xcode project warning, Swift language-mode, concurrency, and upcoming-feature policies.
- Added completion-audit enforcement for compiler settings in checked-in Swift packages.

### Changed

- Required future Xcode compiler-policy changes to evaluate and update Swift Package Manager parity when an equivalent package setting is applicable.

## [0.0.32] - 2026-09-13

### Changed
Expand Down
41 changes: 41 additions & 0 deletions Guidelines/Packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,47 @@ The common package baseline is Swift, Xcode, Platforms, License, and CI. Add opt
- Put sources under `Sources/<Target>/` and tests under `Tests/<Target>Tests/`.
- Keep resources in the target that owns them and use the package bundle for lookup.

## Compiler settings baseline

Host Xcode build settings are not a substitute for package configuration. Each package must express its applicable compiler policy in `Package.swift` so independently invoked SwiftPM builds, Xcode builds, and dependency builds receive the same strictness. This baseline is the SwiftPM representation of the applicable compiler policy in [Xcode project settings](Xcode/ProjectSettings.md), not a mechanical copy of Xcode build-setting names.

New packages must use the newest supported Swift tools version. Every package must use the newest stable Swift language mode supported by the selected toolchain, currently Swift 6, preferably owned once at package level:

```swift
swiftLanguageModes: [.v6]
```

Do not repeat `.swiftLanguageMode(.v6)` target by target when package-level ownership is sufficient. A target may specialize the language mode only under a documented package exception. An older manifest that cannot express this baseline must first modernize its tools version; `.treatAllWarnings(as:)` requires PackageDescription 6.2 or later.

Every locally defined target that compiles Swift and for which SwiftPM exposes `swiftSettings`, including test targets and other applicable Swift target kinds, must unconditionally use the typed PackageDescription API:

```swift
swiftSettings: [
.treatAllWarnings(as: .error),
.enableUpcomingFeature("ExistentialAny"),
.enableUpcomingFeature("InferIsolatedConformances"),
.enableUpcomingFeature("InternalImportsByDefault"),
.enableUpcomingFeature("MemberImportVisibility"),
.enableUpcomingFeature("NonisolatedNonsendingByDefault"),
]
```

A setting restricted only to Debug, Release, a platform, or another build condition does not satisfy this package-wide baseline unless a documented exception covers that scope. Do not use `unsafeFlags` for warning handling when the typed API is available.

When a locally compiled target contains C or Objective-C, require `cSettings: [.treatAllWarnings(as: .error)]`. Where C++ settings apply, require `cxxSettings: [.treatAllWarnings(as: .error)]`. Pure-Swift packages do not need C or C++ settings, and packages must not introduce `-Werror` through `unsafeFlags` when the typed APIs are available.

Swift 6 language mode enables complete concurrency checking unconditionally, so a Swift 6 package must not retain any explicit `StrictConcurrency` opt-in. Remove `.enableUpcomingFeature("StrictConcurrency")`, `.enableExperimentalFeature("StrictConcurrency")`, and `StrictConcurrency=complete` spellings instead of treating one representation as special. For an older package, modernize to the required language mode instead of preserving the legacy mode with a compatibility flag.

Do not invent a direct SwiftPM equivalent for `SWIFT_APPROACHABLE_CONCURRENCY`. Its applicable opt-in language behavior is represented by the individual upcoming features above, including `InferIsolatedConformances` and `NonisolatedNonsendingByDefault`.

`.defaultIsolation(MainActor.self)` is intentionally not part of this shared package baseline. Reusable packages must express actor isolation according to their public and internal API semantics rather than inherit an application's default isolation policy. A package may choose a default isolation as an intentional package-specific architectural decision, but the completion audit must not add or require it merely for Xcode-project parity.

Require the listed upcoming features on every applicable locally defined Swift target, but not on binary or system-library targets that SwiftPM does not compile as Swift source or package plug-in targets for which `Target.plugin(...)` does not expose `swiftSettings`. Reevaluate the list whenever the selected Xcode/Swift toolchain or language mode changes. When a feature becomes unconditional in the selected language mode, remove its `.enableUpcomingFeature(...)` declaration from packages, remove it from this baseline, and update the audit contract in the same change. Retain no redundant upcoming features merely for historical consistency because they can produce diagnostics under warnings-as-errors.

Metal warnings-as-errors and application `Info.plist` export-compliance declarations have no package equivalent in this baseline. SwiftPM has no first-class Metal warning setting, and a reusable package does not own its consuming application's generated `Info.plist`.

Accept a deviation only when the nearest applicable `AGENTS.md`, or durable documentation linked from it, records the exact package compiler setting or feature, affected package and targets, concrete incompatibility, replacement or omission, engineering impact, compensating validation where applicable, and condition for revisiting or removing the exception. Do not infer an exception from the existing `Package.swift`.

## Logging

Packages own any diagnostics emitted by their implementation. Follow the shared [logging guide](Logging.md) for AppLogger usage, subsystem identity, package emoji prefixes, domain-owned categories, concise messages, privacy, and test coverage. A consuming application must not reproduce package-internal logs.
Expand Down
4 changes: 4 additions & 0 deletions Guidelines/Xcode/ProjectSettings.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ The Xcode 27 inventory to evaluate is:

Treat this list as discovery input for Xcode 27, not as a set of flags that must all be present and not as a permanent exhaustive list. When adopting a newer Xcode, compare its build settings with this prefix and evaluate newly exposed settings against the selected Swift language mode. Require each still-upcoming feature at project level; omit each feature already incorporated into the language mode.

## Swift package parity

Whenever this Xcode project baseline adds, removes, or changes a Swift or Clang compiler policy, evaluate whether Swift Package Manager exposes a semantically equivalent setting and whether that policy is appropriate for reusable packages. When it is, update the [Swift package compiler-settings baseline](../Packages.md#compiler-settings-baseline), the Swift-package completion audit, and their structural validation in the same change. Do not mechanically copy application-only policy such as `Info.plist` declarations, Metal settings without a SwiftPM equivalent, or default MainActor isolation into the package baseline.

## Audit procedure

1. Identify the selected Xcode version and its newest stable Swift language mode.
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ From the consumer repository root, install a tagged release:
git subtree add \
--prefix=AgentGuidelines \
https://github.com/thatfactory/agent-guidelines.git \
0.0.32 \
0.0.33 \
--squash
```

Expand Down Expand Up @@ -147,7 +147,7 @@ Review the target release's changelog, then pull it deliberately:
git subtree pull \
--prefix=AgentGuidelines \
https://github.com/thatfactory/agent-guidelines.git \
0.0.32 \
0.0.33 \
--squash
```

Expand Down
61 changes: 61 additions & 0 deletions Scripts/validate_guidelines.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ let upcomingFeatureSettings = [
"SWIFT_UPCOMING_FEATURE_NONISOLATED_NONSENDING_BY_DEFAULT",
"SWIFT_UPCOMING_FEATURE_REGION_BASED_ISOLATION",
]
let packageUpcomingFeatures = [
"ExistentialAny",
"InferIsolatedConformances",
"InternalImportsByDefault",
"MemberImportVisibility",
"NonisolatedNonsendingByDefault",
]

/// Returns all regular-expression matches in a string.
func matches(_ pattern: String, in value: String) -> [NSTextCheckingResult] {
Expand Down Expand Up @@ -525,6 +532,10 @@ func validateXcodeProjectSettingsGuideline(_ errors: inout [String]) {
"unit-test and UI-test targets": "test-target effective-value audit",
"nearest applicable `AGENTS.md`": "local exception source",
"condition for removing or revisiting the exception": "exception lifecycle",
"## Swift package parity": "Swift package parity section",
"../Packages.md#compiler-settings-baseline": "Swift package baseline cross-reference",
"Whenever this Xcode project baseline adds, removes, or changes a Swift or Clang compiler policy":
"package applicability maintenance rule",
]
for (value, description) in required where !contents.contains(value) {
errors.append("Guidelines/Xcode/ProjectSettings.md: missing \(description): '\(value)'")
Expand All @@ -535,6 +546,38 @@ func validateXcodeProjectSettingsGuideline(_ errors: inout [String]) {
}
}

/// Validates the Swift package compiler-settings contract.
func validatePackageCompilerSettingsGuideline(_ errors: inout [String]) {
guard let contents = readText(packagesGuideline, errors: &errors) else {
return
}
let required = [
"## Compiler settings baseline": "compiler-settings baseline section",
"Xcode/ProjectSettings.md": "Xcode baseline cross-reference",
"swiftLanguageModes": "package-level Swift language mode",
".treatAllWarnings(as: .error)": "typed warnings-as-errors policy",
"Swift 6 language mode enables complete concurrency checking unconditionally":
"Swift 6 strict-concurrency explanation",
".enableUpcomingFeature(\"StrictConcurrency\")":
"upcoming StrictConcurrency redundancy rule",
".enableExperimentalFeature(\"StrictConcurrency\")":
"experimental StrictConcurrency redundancy rule",
"StrictConcurrency=complete": "explicit StrictConcurrency redundancy rule",
"`.defaultIsolation(MainActor.self)` is intentionally not part":
"default MainActor isolation exclusion",
"package plug-in targets for which `Target.plugin(...)` does not expose `swiftSettings`":
"unsupported plug-in target exclusion",
"Retain no redundant upcoming features": "redundant upcoming-feature prohibition",
"condition for revisiting or removing the exception": "package-setting exception lifecycle",
]
for (value, description) in required where !contents.contains(value) {
errors.append("Guidelines/Packages.md: missing package compiler policy \(description): '\(value)'")
}
for feature in packageUpcomingFeatures where !contents.contains(".enableUpcomingFeature(\"\(feature)\")") {
errors.append("Guidelines/Packages.md: missing required SwiftPM upcoming feature '\(feature)'")
}
}

/// Validates the shared App Store metadata workflow.
func validateAppStoreGuideline(_ errors: inout [String]) {
guard let contents = readText(appStoreGuideline, errors: &errors) else {
Expand Down Expand Up @@ -674,10 +717,27 @@ func validateAuditSkill(_ errors: inout [String]) {
"Guidelines/CICD.md": "shared CI/CD guide reference",
"fastlane adoption": "forbidden delivery-tooling audit",
"missing Swift capability": "non-Swift script exception audit",
"## Audit Swift package settings": "Swift package-settings audit",
"Guidelines/Packages.md#compiler-settings-baseline": "shared package compiler-settings guide reference",
"Package.swift": "package manifest discovery",
"swift package --package-path <package-root> dump-package": "evaluated manifest inspection",
"swiftLanguageModes": "package language-mode audit",
".treatAllWarnings(as: .error)": "package warnings-as-errors audit",
".enableUpcomingFeature(...)": "package upcoming-feature audit",
"complete strict concurrency as supplied by the language mode": "Swift 6 strict-concurrency handling",
".enableUpcomingFeature(\"StrictConcurrency\")": "upcoming StrictConcurrency removal audit",
".enableExperimentalFeature(\"StrictConcurrency\")": "experimental StrictConcurrency removal audit",
"StrictConcurrency=complete": "explicit StrictConcurrency removal audit",
".defaultIsolation(MainActor.self)": "default MainActor isolation exclusion",
"package plug-in targets": "unsupported plug-in target exclusion",
"package-setting failure": "package-setting exception lookup",
]
for (value, description) in required where !contents.contains(value) {
errors.append(".agents/skills/agent-guidelines-audit/SKILL.md: missing \(description): '\(value)'")
}
for feature in packageUpcomingFeatures where !contents.contains(feature) {
errors.append(".agents/skills/agent-guidelines-audit/SKILL.md: missing package feature audit '\(feature)'")
}
validateExecutable(markdownWrappingScript, description: "Markdown wrapping checker", errors: &errors)
validateExecutable(stringCatalogInspectionScript, description: "String Catalog inspection checker", errors: &errors)
if let development = readText(developmentGuideline, errors: &errors),
Expand Down Expand Up @@ -748,6 +808,7 @@ func main() -> Int32 {
validateAppStoreGuideline(&errors)
validateLocalizationScripts(&errors)
validateXcodeProjectSettingsGuideline(&errors)
validatePackageCompilerSettingsGuideline(&errors)
validateExternalDependencyPolicy(&errors)
validateGitignoreGuidance(&errors)
validateExecutable(consumerSetupScript, description: "consumer setup validator", errors: &errors)
Expand Down
Loading