关于 adversarial-swift-ui
用于按架构、生命周期、视图身份、性能和无障碍规则审查 SwiftUI 代码的技能。盲审者给出通过或失败判定;该技能不修复代码。
主要功能
- 01盲式对抗审查
- 02PASS/FAIL/N/A 判定
- 03七类 SwiftUI 规则
- 04工具链与部署版本门槛
- 05基于证据的判定报告
适用场景
- 01合并前审查 SwiftUI 改动
- 02审计 Agent 编写的视图
- 03检查 UIKit 到 SwiftUI 的移植
- 04验证无障碍规范
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ pproenca/ dot-skills --skill adversarial-swift-ui安装后在 Claude Code 中输入/adversarial-swift-ui确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
gotchas.mdmetadata.jsonassets/templates/verdict.mdreferences/_sections.mdaccess-button-not-ontapgesture.mdaccess-button-title-and-icon.mdaccess-representation-for-custom-controls.mdaccess-scaledmetric-custom-spacing.mdaccess-semantic-fonts-and-colors.mdaccess-style-protocols-for-custom-controls.mdanim-body-scoped-animation-in-generic-containers.mdanim-builtin-effects-over-custom-animatable.mdidentity-anylayout-over-container-branches.mdidentity-branch-free-modifier-helpers.mdidentity-branch-in-modifier-not-around-view.mdlist-constant-foreach-view-count.mdlist-no-anyview-rows.mdlist-no-geometry-feedback-loop.mdlist-ongeometrychange-over-georeader.mdlist-visualeffect-for-render-transforms.mdreviewer-prompt.mdstate-callasfunction-env-closures.mdstate-guard-task-id-model-reinit.mdstate-no-highfreq-environment-values.mdstate-no-initialvalue-from-params.mdstate-observable-not-observableobject.mdstate-own-models-in-state.mdtask-concurrent-offload-cpu-work.mdtask-id-for-async-state-reactions.mdtask-modifier-not-onappear-task.md详细介绍
对抗式 SwiftUI 审查门禁
SwiftUI 架构审查门禁——通过/失败:由一个盲审子 Agent 根据此门禁的规则进行裁定,并采取对抗式审查立场;只有每条规则均为 PASS 或 N/A 时,工作才算通过。此技能只给出判定,绝不修复工作内容。
这些规则筛选自审查者仅凭代码证据即可判定的检查项。门禁针对 Agent 和经验丰富但尚非专家的开发者实际会造成的失效模式进行判定:旧式观察机制栈、破坏身份的条件语句、绑定到错误生命周期节点的工作、破坏列表惰性加载的构建方式、泄漏到泛型内容中的动画,以及放弃系统无障碍语义的控件。
适用时机
- SwiftUI 差异、功能或 PR 即将合并,需要客观的 PASS/FAIL 判定,而非建议性反馈。
- Agent(Claude、Codex)编写了视图,你希望进行独立检查,确认其没有重复使用 Observation 之前的惯用写法(
ObservableObject/@StateObject、.onAppear { Task { ... } }、AnyView行、用于测量的GeometryReader),也没有使用会重置身份的条件写法(applyIf辅助方法、切换容器类型)。 - 正将 UIKit 时代的屏幕迁移到 SwiftUI,需要根据框架的更新机制(子视图边界、最小化依赖、缓存派生值、稳定身份)审查新界面。
- 必须验证无障碍与平台惯例是否合规,而不能想当然——仅图标按钮、伪装成控件的点击手势、存在样式协议却自行重建的基础控件、静默的 Canvas 控件、硬编码字体、文本周围固定间距。
不要将此门禁用于没有 SwiftUI 界面的目标——服务端 Swift、CLI 工具、非 UI 包(审查提示词的前置条件会中止并返回“GATE NOT APPLICABLE”)。通用 Swift 语言质量(并发结构、API 设计、控制流)属于同级的 adversarial-swift 门禁,而非本门禁的职责。若修复措施需要的工具链或部署目标版本高于项目所用版本,则相关规则应为 N/A,而非 FAIL——审查提示词中附有版本门槛表。
审查流程
严格遵循以下步骤——此门禁的价值在于每次审查都采用相同流程。
步骤 1 前有两个前置条件——两者都存在,是因为违反它们会触发此门禁系列记录在案的现场失效模式(2026 年 7 月:门禁被用作清理工作的驱动器,在目标持续变动时运行,结果未能产生任何判定,而差异已扩大到 33 个文件):
- 冻结目标。 仅针对固定引用执行——提交 SHA、stash 或已保存的差异,并将其记录为目标清单。如果正在审查的代码仍在变化(工作树持续收集修改,或其他 Agent 正在修改它),则不要派发审查。若审查进行期间目标发生变化,本次运行即作废:以
GATE VOID — target changed代替判定,并针对新的冻结状态重新派发。已派发的门禁必须始终以生成判定、GATE NOT APPLICABLE或记录作废告终——不得无声结束,因为无法区分无声结束和“已审查”。 - 给出判定,而非清理代码。 此门禁是对已完成工作的最终检查。“运行门禁并激进地修复所有问题”颠倒了约定,也是已记录的范围失控途径:先实现,再冻结,最后运行门禁。出现 FAIL 后,调用方只能在原始目标范围内应用修复;重新审查时,应针对同一目标清单派发一位新的盲审者——各轮审查的范围不得扩大;新增代码意味着必须启动一次带有独立清单的新门禁调用。
当审查期间其他 Agent 可能修改工作区时,审查者应从不可变快照读取规则(例如 git archive <ref> <skill-dir> | tar -x -C "$TMPDIR"),而非读取实时检出目录;技能目录属于只读基础设施,所有清理或修复范围都必须将其排除。
- 确定目标。 明确指出审查对象(差异、一组文件或 PR),并记录引用和路径,确保审查针对明确且固定的目标进行。记录 Swift 工具链版本和最低部署目标(从
Package.swift、Xcode 项目或可用性注解中获取)——若干规则会根据这些信息进行版本判断。在目标描述中包含仓库根目录——update-pass-minimal-data、state-own-models-in-state和update-cache-expensive-derivations可能要求阅读差异块以外的整个文件。 - 加载规则。 阅读 references/_sections.md 和
references/中的每个规则文件(所有state-*.md、update-*.md、identity-*.md、task-*.md、list-*.md、anim-*.md、access-*.md文件)。 - 编写审查提示词。 将规则、目标以及工具链和部署信息填入 references/reviewer-prompt.md。编写好的提示词必须完全自包含——审查者看不到对话历史,因此不得引用提示词以外的上下文。
- 派发一名盲审查者。 启动一个 Task 子 Agent,其全部输入仅为编写好的提示词——不得附带对话上下文或其他说明。
- 以失败关闭方式给出结果。 审查者的结构化输出就是最终判定——不再进行合并。仅当每条规则的结果均为 PASS 或 N/A 时,总体判定才为 PASS;任何一条 FAIL 都会导致门禁失败。绝不求平均、权衡严重性或豁免规则——即使是“轻微”的 FAIL 也仍是 FAIL。如果审查者返回“GATE NOT APPLICABLE”(不存在 SwiftUI 界面),则停止并报告该结果,不得给出判定。
- 呈现判定结果。 填写 assets/templates/verdict.md。若为 FAIL,将审查者给出的“通过所缺条件”建议汇总到修复清单中,每项注明位置,并按类别重要性排序。每条最终结果为 FAIL 的规则都必须出现在修复清单中,并给出具体到可直接照做的更改——如果审查者的建议只是重述违规内容,则在呈现结果前依据规则中的 Correct 示例推导出修复方案。修复清单是用于核验的材料——用于证明每条 FAIL 都可判定且可翻转,而不是待办事项列表:每项修复都必须指出在已声明目标范围内、能够翻转该规则的最小更改;若为满足规则而使用不安全的逃生方案(
@unchecked Sendable、try!、强制解包),则不算翻转规则。审查者发现的目标清单范围外违规,应列入判定结果中的范围外观察项——供未来调用门禁时参考,本次不得修复,也不得计入判定结果。
如果同一规则在未更改的目标上多次复审时给出不同判定,或者人工查看证据后推翻判定,则说明该规则存在可判定性缺陷——将其记录在 gotchas.md 中并完善规则;不得推翻门禁结果。
判定格式
审查者必须为每条规则返回以下内容:PASS | FAIL | N/A、证据(file:line 或引文——PASS 和 FAIL 都必须提供证据);对于每条 FAIL,还必须给出应用后即可将该规则翻转为 PASS 的修复方案——注明具体更改及其位置,不能只是重述违规内容。最终报告遵循 assets/templates/verdict.md。
规则类别
| # | 类别 | 前缀 | 涵盖内容 |
|---|---|---|---|
| 1 | 数据建模与观察 | state- | 相较于 ObservableObject 使用 @Observable、由 @State 持有视图创建的模型、不从 init 参数设置 State(initialValue:)、在 .task(id:) 中重建模型时使用身份检查、为环境闭包使用 callAsFunction 包装器、不在 EnvironmentValues 中存放高频变化的值 |
| 2 | 视图更新开销 | update- | 使用子视图结构体而非计算属性 some View 变量、每个叶视图仅传递必要数据、视图 init 中不执行副作用、缓存 O(n) 派生计算、列表行中不使用包含集合的结构体 |
| 3 | 视图结构身份 | identity- | 在修饰符值内部而非视图周围使用分支、修饰符辅助方法(applyIf)中不使用运行时 if/else、容器分支使用 AnyLayout |
| 4 | 数据加载与任务生命周期 | task- | 使用 .task 而非 .onAppear+Task、使用 .task(id:) 而非 .onChange+Task、比较标量值、在 @MainActor 可观察对象中使用 @concurrent 执行 CPU 密集型任务 |
| 5 | 列表与几何布局 | list- | ForEach 中每个元素的视图数量保持恒定、行视图不使用 AnyView、使用 onGeometryChange 而非用于测量的 GeometryReader、避免几何反馈循环、使用 visualEffect 实现由滚动驱动的变换 |
| 6 | 动画范围 | anim- | 通用容器使用 animation(_:body:),而非在任意内容上使用基于值的 .animation、优先使用内置可动画属性而非自定义 Animatable |
| 7 | 平台惯例与无障碍功能 | access- | 使用标题和图标构建按钮、使用 Button 而非 onTapGesture、使用样式协议而非重建控件、为定制控件提供无障碍表征、使用语义字体和颜色、在文本附近使用 @ScaledMetric 设置自定义间距 |
注意事项
在派发审查器之前,请阅读 gotchas.md — 其中预先记录了规则忠实性防护措施(本检查关卡规则认可但社区常识反对的模式,例如在常量集合上使用 id: \.self,以及使用 @State 持有视图模型),以免审查器引入外部规则。
相关技能
adversarial-swift— 负责 Swift 语言问题的同级检查关卡(并发、错误传播、API 与类型设计、控制流);处理混合 Swift+SwiftUI 工作时,请同时运行两者。adversarial-ios-design— 负责渲染设计与 UX 的同级检查关卡(HIG 规范、动效、必须捕获证据);面向用户的工作也请运行它;如果差异会改变手势或交互行为,则应先运行它 — 识别器仲裁在此关卡的纯代码审查中不可见。ios-taste(精选)— 本关卡有意排除的 iOS 设计判断指南;目标是评估品味而非给出判定时,请使用它。search-ios26-docs/search-macos26-docs— 当版本门槛问题决定某条规则时,用于验证当前 SDK 的 API 可用性。
参考文件
| 文件 | 描述 |
|---|---|
| references/reviewer-prompt.md | 供盲审查器使用的独立提示词模板 |
| assets/templates/verdict.md | 判定报告模板 |
| references/_sections.md | 类别定义与排序 |
| metadata.json | 版本与来源参考 |