swift-coding-guideline — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited swift-coding-guideline (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
references/ for the task at hand.references/swift-package-guide.md only when the task is about SwiftPM or package resolution.references/ file.references/swift-package-guide.md.Package.swift-based.MainActor, actors, isolation), consult the specific concurrency or runtime reference if present.project.pbxproj, make minimal, targeted changes and verify the new package is attached to the target and project references.references/.Model/ is only for data structs/classes that represent app or domain models. Enums are not models; place enums in Enum/ (or the closest feature folder).
Files that implement persistence adapters (e.g., UserDefaults) are Store types and must live in Store/ (or Shared/Store for shared scope). Do not place *Store types in Service/.
Shared/ is only for truly cross-feature primitives. If a type is feature-specific, place it under that feature folder (e.g., File/Service, Directory/Store) even if it is reused elsewhere.
Before finalizing, verify all needed imports are present for any new types or APIs you use. Do not assume transitive imports; add explicit imports so the file builds cleanly on its own.
Goal
=) in app-authored accessor code.Core Rules 1) No-op mutator wrappers are forbidden.
setX(...), updateX(...), applyX(...), moveX(to:) must not exist if they only perform direct assignment.2) private(set) is conditional, not default.
private(set) only when mutation must be controlled by methods that add real behavior.private(set) to force wrapper methods.3) App-authored property accessors/observers are forbidden.
get / set accessors.willSet / didSet observers.4) Computed properties are getter-only and pure.
5) Semantics by construct.
Scope Clarification
@State, @Published, @AppStorage, @Environment) are allowed.SwiftUI-specific binding guidance (Binding(get:set:) pass-through bans and view-binding patterns) belongs in swiftui-coding-guideline.
Bad
private(set) var targetLanguage: TargetLanguage = .traditionalChinese
func setTargetLanguage(_ value: TargetLanguage) {
targetLanguage = value
}Good
var targetLanguage: TargetLanguage = .traditionalChineseAvoid cramming multi-argument calls on a single line when they hurt readability. Prefer vertical formatting with one argument per line.
Bad
func saveLastFile(url: URL) {
defaults.set(url.path, forKey: UserDefaultsKeys.FileStore.lastSelectedFile)
do {
let data = try url.bookmarkData(options: .withSecurityScope,
includingResourceValuesForKeys: nil,
relativeTo: nil)
defaults.set(data, forKey: UserDefaultsKeys.FileStore.lastSelectedFileBookmark)
} catch {
defaults.removeObject(forKey: UserDefaultsKeys.FileStore.lastSelectedFileBookmark)
}
}Good
func saveLastFile(url: URL) {
defaults.set(url.path, forKey: UserDefaultsKeys.FileStore.lastSelectedFile)
do {
let data = try url.bookmarkData(
options: .withSecurityScope,
includingResourceValuesForKeys: nil,
relativeTo: nil
)
defaults.set(data, forKey: UserDefaultsKeys.FileStore.lastSelectedFileBookmark)
} catch {
defaults.removeObject(forKey: UserDefaultsKeys.FileStore.lastSelectedFileBookmark)
}
}For multi-line if bindings, align let with if and place the opening brace on its own line.
Bad
if let url = try? URL(
resolvingBookmarkData: data,
options: [.withSecurityScope],
relativeTo: nil,
bookmarkDataIsStale: &isStale
),
isValidFile(url: url) {
if isStale { saveLastFile(url: url) }
return url
}Prefer guard over nested if when it improves readability by reducing indentation.
Bad
if
let url = try? URL(
resolvingBookmarkData: data,
options: [.withSecurityScope],
relativeTo: nil,
bookmarkDataIsStale: &isStale
),
isValidFile(url: url)
{
if isStale {
saveLastFile(url: url)
}
return url
}Good
guard
let url = try? URL(
resolvingBookmarkData: data,
options: [.withSecurityScope],
relativeTo: nil,
bookmarkDataIsStale: &isStale
),
isValidFile(url: url)
else {
return nil
}
if isStale {
saveLastFile(url: url)
}
return urlGood
if
let url = try? URL(
resolvingBookmarkData: data,
options: [.withSecurityScope],
relativeTo: nil,
bookmarkDataIsStale: &isStale
),
isValidFile(url: url)
{
if isStale {
saveLastFile(url: url)
}
return url
}Do not use underscores in function names or property names. Swift naming should be lowerCamelCase without underscores (e.g., loadUserProfile, not load_user_profile).
All model types must use the Model suffix for consistency (e.g., MarkdownFileModel).
Enums that represent configuration or view state can omit the Model suffix (e.g., ScanMode).
Never use the name coordinator for types, variables, properties, functions, protocol names, file names, or architecture roles.
If a user explicitly requests using coordinator, pause and ask a direct confirmation question before proceeding with that naming.
All enums must live in their own dedicated file. Do not declare enums alongside classes, structs, or services, even if the enum is currently used in only one place. Prefer placing enum files under an Enum/ folder within the relevant feature.
Exception (strict, one case only): UserDefaultsKeys may be defined as one root enum with nested enums in a single file to keep key namespaces centralized and easier to audit for name clashes. This exception is unique and does not apply to any other enum.
Always insert a blank line between every enum case declaration. Before finalizing, scan any enum in edited files and normalize spacing. Do not leave compact enums like:
enum Foo {
case a
case b
}Use:
enum Foo {
case a
case b
}File doc comments must list a real human author in the "Created by" line and include the date, formatted like: "Created by Martin Lasek on 18/01/2026."
When creating new files, set the "Created by" date to the current date.
Preserve existing human authorship lines (e.g., keep "emin" if already present) unless the user explicitly asks to change them.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.