ECC swift-reviewer:面向 Kiro 的分层 Swift 代码审查代理设计与全量审查标准
【免费下载链接】ECCThe agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.项目地址: https://gitcode.com/GitHub_Trending/ev/ECC
本篇指南以 ECC 仓库中 Kiro 代理定义文件 .kiro/agents/swift-reviewer.md 为主体,完整解析这位"资深 Swift 代码审查者"的调用流程、CRITICAL/HIGH/MEDIUM 三级审查标准、诊断命令集与审批决策规则,并结合仓库中同名的 Claude Code 版本代理 agents/swift-reviewer.md、配套技能 skills/swift-actor-persistence/SKILL.md、skills/swift-protocol-di-testing/SKILL.md 以及 rules/swift/security.md 做源码级佐证。读完后,你将掌握一套可直接落地到 Swift 项目的 AI 审查流程:从swift build/swiftlint/swift test前置检查,到逐条对齐安全、错误处理、并发、内存、协议导向设计的审查清单,再到 Approve/Warning/Block 的审批判定。
代理定位与配置
.kiro/agents/swift-reviewer.md采用 Kiro 的 Markdown 代理定义格式:YAML frontmatter 声明元信息,正文即注入给模型的系统提示词。其 frontmatter 完整内容如下:
name: swift-reviewer description: Expert Swift code reviewer specializing in protocol-oriented design, value semantics, ARC memory management, Swift Concurrency, and idiomatic patterns. Use for all Swift code changes. MUST BE USED for Swift projects. allowedTools: - read - shell各字段的作用可以直接从配置本身读出:
name:代理在 Kiro 中的注册名,用于在会话中按名称调用;description:触发描述。特别值得注意的是其中的强制性措辞——"Use for all Swift code changes. MUST BE USED for Swift projects.",即凡是涉及 Swift 代码变更的场景都应路由到该代理,这是 ECC 代理体系中典型的"单用途专家代理"命名法(仓库agents/目录下还有python-reviewer、rust-reviewer等同构定义);allowedTools:只授予read(读文件)与shell(执行诊断命令)两类工具。这一定权策略是刻意的:审查者只需要"看代码 + 跑验证命令",不需要写文件,从而在工具层面限制了审查过程中的副作用。
Kiro 同时为该代理提供了一份 JSON 清单 .kiro/agents/swift-reviewer.json,从源码结构看这是 Kiro 代理定义的双格式表示:JSON 中allowedTools为["fs_read", "shell"],tools为["@builtin"],mcpServers与hooks均为空对象,prompt字段则完整内嵌了与 Markdown 版本逐字相同的系统提示词。两份文件描述同一代理,便于不同加载机制消费。
调用流程:先跑验证,再谈审查
文档正文开头定义了代理被调用时的 5 步标准动作:
- 运行
swift build、swiftlint lint --quiet(如已安装)和swift test——任何一项失败就立即停止并报告,不进入逐行审查; - 运行
git diff HEAD~1 -- '*.swift'查看最近一次提交的 Swift 文件变更(PR 场景改用git diff main...HEAD -- '*.swift'); - 审查范围锁定为被修改的
.swift文件,而不是全量代码; - 若项目有 CI 或合并要求,审查默认假设 CI 为绿色、合并冲突已解决;如果 diff 本身暗示 CI 可能失败(例如测试改动与实现不匹配),需要明确指出;
- 开始按审查标准逐项检查。
这套流程体现了一个务实的审查经济学:构建与测试失败时,代码级的风格问题毫无意义,所以第一步是"硬闸门"(hard gate);第二步用git diff限定审查面,避免 AI 审查常见的"全库漫游、泛泛而谈"问题。
分层审查标准
文档将审查项组织为 CRITICAL → HIGH → MEDIUM 三个严重度层级,共 8 个专项。以下完整继承原文标准,并逐条给出判定依据与仓库佐证。
CRITICAL - Safety(安全)
任何一条命中即触发 Block:
| 审查项 | 判定与整改建议 |
|---|---|
| 强制解包 | 生产代码路径中的value!——改用guard let、if let或?? |
| 强制 try | 无合理理由的try!——改用do/catch或以throws向上传播 |
| 强制转换 | 未做前置类型检查的as!——改用as?配合条件绑定 |
| 硬编码密钥 | 源码中出现 API key、密码、token——改用 Keychain 或环境变量 |
| UserDefaults 存敏感数据 | 敏感数据写入UserDefaults——改用 Keychain Services |
| SQL/命令注入 | 在查询语句或 shell 命令中使用字符串插值 |
| 路径穿越 | 用户可控路径未经校验 |
| 不安全反序列化 | 解码不可信数据时没有校验或大小限制 |
其中"硬编码密钥"与"UserDefaults 存密钥"两条,在仓库的 Swift 安全规则 rules/swift/security.md 中有更完整的展开:该文件声明敏感数据(token、密码、密钥)必须走 Keychain Services,构建期密钥用环境变量或.xcconfig,并给出环境变量取值的示例代码:
let apiKey = ProcessInfo.processInfo.environment["API_KEY"] guard let apiKey, !apiKey.isEmpty else { fatalError("API_KEY not configured") }同时该文件还强调了传输安全(ATS 默认强制开启、关键端点做证书固定)与输入校验(外部来源数据——API、深链、粘贴板——须先校验再处理)。这些正是审查代理在实际执行 "CRITICAL - Safety" 检查时可以直接对标的规则文件。
CRITICAL - Error Handling(错误处理)
| 审查项 | 说明 |
|---|---|
| 被吞掉的错误 | 空catch {}块,或用try?丢弃有意义的错误 |
| 缺少错误上下文 | 直接重新抛出,而没有包装成领域特定错误 |
fatalError()用于可恢复条件 | 调用方本可以处理的错误应使用throw |
assert用于必要不变式 | assert在 release 构建中会被剥离——应改用precondition |
第 4 条值得展开:Swift 中assert只在调试构建生效,若某个不变式在 release 下也必须成立(例如数组索引合法性),用assert会导致检查在发布版中"静默消失"。precondition在调试与发布构建中都会强制检查,因此"必要不变式"必须用后者。
HIGH - Concurrency(并发)
Swift Concurrency 是当前 Swift 项目缺陷最集中的区域,文档列出 6 条:
- 数据竞争:可变共享状态没有 actor 隔离或同步手段;
@Sendable违规:非Sendable类型跨越隔离边界传递;- 阻塞主 actor:在
@MainActor上执行同步 I/O 或Thread.sleep; - 无取消的非结构化
Task {}:fire-and-forget 任务泄漏; - actor 重入问题:跨
await挂起点时对状态一致性做了错误假设——actor 在await处挂起时允许其他任务进入,"读-改-写"跨挂起点时可能观察到中间状态; - 缺失
@MainActor:UI 更新在主 actor 之外执行。
HIGH - Memory Management(内存管理)
ARC 引用计数模型下的四个经典陷阱:
- 强引用循环:长生命周期上下文中闭包强捕获
self——使用[weak self]; - Delegate 强引用:delegate 属性未声明
weak,形成保留环; - 逃逸闭包缺少捕获列表:没有显式声明捕获语义;
- 大值类型拷贝:过大的
struct在每次赋值时整体复制。
HIGH - Code Quality(代码质量)
- 超大函数:超过 50 行;
- 深层嵌套:超过 4 层;
- 演进枚举上的通配 switch:
default:会掩盖未来新增的 case——应使用@unknown default(它会提示开发者该 default 分支可能不再必要); - 死代码:未使用的函数、import 或变量。
HIGH - Protocol-Oriented Design(协议导向设计)
这是该代理区别于通用代码审查器的核心特色(frontmatter 中 "protocol-oriented design, value semantics" 即指向此节):
- 协议已足够却用类继承:优先协议遵循 + 默认扩展实现复用;
Any/AnyObject滥用:改用带约束的泛型或any Protocol/some Protocol;- 缺失协议遵循:类型本应遵循
Equatable、Hashable、Codable或Sendable却没有。
MEDIUM - Performance(性能)
- 热路径上的不必要分配:在紧凑循环内创建对象;
- 缺少
reserveCapacity:已知最终容量却逐元素增长数组; - 循环内字符串插值:重复触发
String分配; - N+1 查询:在循环内发起数据库或网络调用。
MEDIUM - Best Practices(最佳实践)
- 可用
let时用了var:优先不可变绑定; - 可用
struct时用了class:数据模型优先值类型; - 生产代码中的
print():应使用os.Logger或结构化日志; - 缺失访问控制:类型默认为
internal,而本应是private; - 公开 API 无文档:
public成员缺少///文档注释; - 魔法数字/字符串:应使用命名常量或枚举。
诊断命令集
文档给出了一组可直接复制执行的诊断命令:
swift build if command -v swiftlint >/dev/null 2>&1; then swiftlint lint --quiet; else echo "[info] swiftlint not installed"; fi swift test swift package resolve要点解读:
swift build与swift test是 SwiftPM 项目的标准构建/测试入口,覆盖所有 SPM 可构建目标;swiftlint一行使用了command -v做存在性探测——代理不能假设开发者机器上装了 SwiftLint,因此"可选工具"都采用"有则运行、无则降级提示"的写法;swift package resolve重新解析依赖图,用于排除"依赖声明与 lockfile 不一致"这类导致本地构建偶发失败的问题。
审批决策标准
审查结论收敛为三档:
- Approve(通过):无 CRITICAL 或 HIGH 问题;
- Warning(警告):仅存在 MEDIUM 问题——代码可以合并,但列出改进建议;
- Block(阻断):发现任一 CRITICAL 或 HIGH 问题。
文档结尾还给出审查心态基准:"Would this code pass review at a top Swift shop or well-maintained open-source project?"——即所有规则最终服从同一个判定:代码能否经受住头部 Swift 团队或高质量开源项目的评审。
纵深对照:Claude Code 版本代理的增量条款
仓库中同名代理 agents/swift-reviewer.md 是面向 Claude Code 的版本(frontmatter 为tools: Read, Grep, Glob, Bash,并声明model: sonnet)。两者共享同一套五级调用流程与审查骨架,但 Claude Code 版本在多条目上更严格,可以作为 Kiro 版本的"增强参考":
- 安全层新增"ATS disabled"(无合理理由关闭 App Transport Security 视为 CRITICAL);
- 错误处理层新增"
precondition/fatalError用于库代码":precondition在调试与发布构建中都会崩溃,fatalError无条件崩溃,公开 API 边界上应改用throw; - 代码质量层新增"非穷尽匹配"(需要显式处理时却写了兜底分支);
- 协议设计层新增"存在类型优于泛型"(参数可用
some Protocol或泛型约束时却用了any Protocol); - 性能层新增"不必要的
@objc桥接"(纯 Swift 足够时避免 Swift 到 Objective-C 的过桥开销); - 最佳实践层新增"SwiftLint 警告未处理"(无理由的
// swiftlint:disable抑制)与"字符串化 API"(用原始字符串表达本应建模为枚举的值); - 诊断命令新增
swift-format lint -r .的可选探测(同样先command -v判存再执行,并截取前 30 行输出); - 交叉引用不同:Kiro 版本引用技能
swift-actor-persistence、swift-protocol-di-testing;Claude Code 版本则引用规则文件swift/coding-style、swift/patterns、swift/security、swift/testing(对应仓库 rules/swift/ 目录下的同名.md文件)以及技能swift-concurrency-6-2、swiftui-patterns、swift-protocol-di-testing。
从源码结构看,这种"同一专家、多 Harness 变体"是 ECC 的通用组织方式:核心审查逻辑只维护一份,按宿主工具(Kiro / Claude Code)在 frontmatter 的工具体系、安全基线(Claude Code 版本开头有 Prompt Defense Baseline 反提示注入条款)和诊断命令上做适配。
配套技能:审查标准背后的两个 Swift 模式
文档末行将swift-actor-persistence与swift-protocol-di-testing两个技能作为"详细模式与规则"的延伸引用,二者恰好对应审查标准中"并发"与"代码质量/协议设计"两条 HIGH 线的最佳实践落地。
swift-actor-persistence:用 actor 消除数据竞争
技能 skills/swift-actor-persistence/SKILL.md 展示了一个通用的 actor 仓库模式:内存缓存 + 文件持久化,由编译器强制串行化访问,直接消除"数据竞争"审查项。核心结构如下:
public actor LocalRepository<T: Codable & Identifiable> where T.ID == String { private var cache: [String: T] = [:] private let fileURL: URL public init(directory: URL = .documentsDirectory, filename: String = "data.json") { self.fileURL = directory.appendingPathComponent(filename) // Synchronous load during init (actor isolation not yet active) self.cache = Self.loadSynchronously(from: fileURL) } public func save(_ item: T) throws { cache[item.id] = item try persistToFile() } public func find(by id: String) -> T? { cache[id] } private func persistToFile() throws { let data = try JSONEncoder().encode(Array(cache.values)) try data.write(to: fileURL, options: .atomic) } // ... }其关键设计决策(技能内以表格形式给出)包括:用 actor 而非"类 + 锁"获得编译器强制的线程安全;字典按 ID 索引实现 O(1) 查找;泛型约束Codable & Identifiable使其可复用于任意模型;文件写入使用.atomic防止崩溃时出现半写文件。调用侧因为 actor 隔离天然全异步:let question = await repository.find(by: "q-001")。对照审查标准可见,"可变共享状态无 actor 隔离""非Sendable类型跨边界"这类 HIGH 项,在此模式下的标准答案就是把状态收进 actor、把跨边界数据类型约束为Sendable。技能同时列出了反模式清单,例如新并发代码用DispatchQueue/NSLock、用nonisolated绕开 actor 隔离等,与审查代理"fire-and-forget 任务泄漏"等条款形成呼应。
swift-protocol-di-testing:协议化依赖注入
技能 skills/swift-protocol-di-testing/SKILL.md 回答另一个审查关切:如何让"文件/网络/外部 API"相关的 Swift 代码可测试。其模式分五步:
- 定义小而聚焦的
Sendable协议,例如:
public protocol FileAccessorProviding: Sendable { func read(from url: URL) throws -> Data func write(_ data: Data, to url: URL) throws func fileExists(at url: URL) -> Bool }- 提供生产实现(如
DefaultFileAccessor封装Data(contentsOf:)与原子写入); - 编写可注入错误的 mock(
readError/writeError属性用于模拟失败路径); - 通过带默认值的参数注入——生产代码走默认实现,测试只需注入 mock:
public actor SyncManager { public init( fileSystem: FileSystemProviding = DefaultFileSystemProvider(), fileAccessor: FileAccessorProviding = DefaultFileAccessor() ) { /* ... */ } }- 用 Swift Testing 框架断言错误路径,例如
await #expect(throws: SyncError.containerNotAvailable) { try await manager.sync() }。
技能的"仅 mock 边界,不 mock 内部类型"原则,恰好是审查标准中"协议滥用"(Any/AnyObject、过度抽象)条款的反面锚点:抽象应发生在外部依赖边界,而不是渗透进每个内部类型。
如何应用这套审查体系
结合以上各部分,在 Swift 项目中使用该代理的完整路径是:
- 将 .kiro/agents/swift-reviewer.md 放入项目的
.kiro/agents/目录(Kiro 会将其注册为可调用代理;配套 JSON 清单 swift-reviewer.json 一并存在以兼容清单式加载); - 在每次 Swift 变更(提交或 PR)后调用
swift-reviewer,它会按"构建/测试闸门 → diff 定位 → 分层审查 → 三档结论"的流程给出结构化结果; - 对审查中反复命中的模式类问题,按文档末行引用的技能深入修复:线程安全问题参考 swift-actor-persistence 的 actor 仓库模式,可测试性问题参考 swift-protocol-di-testing 的边界协议注入模式;
- 项目级规则可进一步与 rules/swift/security.md、rules/swift/patterns.md 等规则文件对齐,使代理的审查口径与团队规范文件保持同一来源。
这套设计的可取之处在于把"资深 Swift 审查者的隐性经验"显式化为可版本化、可跨项目复用的资产:frontmatter 限定工具与角色,调用流程保证审查有闸门、有边界,分层标准保证结论可判定(Approve/Warning/Block),配套技能保证每个审查项都有对应的正模式可依。适用前提需要说明:该代理面向 Swift Package Manager 可构建项目(诊断命令基于swift build/swift test),SwiftLint 与 swift-format 均为可选依赖,缺失时自动降级为提示而非失败。
【免费下载链接】ECCThe agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.项目地址: https://gitcode.com/GitHub_Trending/ev/ECC
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考