从 0 到 1:Pure for Mac 的 AI 辅助研发实践(一)项目总览
本文是系列第一篇,用于建立项目背景与技术事实基线。数据来自当前仓库与本次实测;无法直接验证的历史信息会标注来源类型。
项目背景与目标
Pure for Mac 的想法,最初来自我自己使用 MacBook 的实际体验。
随着日常使用时间增长,系统缓存、应用日志、临时文件等数据逐渐积累,磁盘空间也需要定期整理。macOS 本身提供了基础的存储管理能力,但在文件浏览、目录定位和清理操作等方面,我个人仍觉得不够直观。相比之下,Windows 上的一些文件管理操作更符合我的使用习惯。
另一方面,部分 macOS 清理工具采用付费模式。对于一个主要想解决个人日常清理需求的用户来说,我希望有一个更符合自己使用习惯、功能透明且能够自主控制的替代方案。
于是,我产生了一个想法:**能不能借助 Vibe Coding,从零开发一款属于自己的 macOS 清理工具?**这也成为 Pure for Mac 的起点。
项目的目标不只是扫描与删除,还希望通过这次实践,探索 AI 编程工具如何参与需求规划、架构设计、功能实现、测试验证与工程化交付。
产品设计上,安全性与可控性优先。清理工具涉及真实文件系统操作,不能只追求清理数量或释放空间的视觉效果;用户需要知道扫描发现了什么、为什么建议清理、删除可能产生什么影响。
因此,Pure for Mac 尝试将清理对象进行风险分级,并在扫描与删除之间设置独立的安全校验,让清理行为尽可能透明、可控。
从个人需求出发,借助 AI 编程工具构建一款具备实际功能的软件,也成为我探索 Vibe Coding 与软件工程实践结合的一次尝试。
本文不复述具体的 AI 对话与生成过程,只讨论仓库中可验证的实现与结果。
用户需求与功能边界
产品把清理对象分成三类,而不是笼统地称为"垃圾":
| 类别 | 处理方式 | 代码中的体现 |
|---|---|---|
| 安全可清理 | 可直接一键清理 | safe/low,允许一键执行 |
| 建议检查 | 必须用户明确确认 | medium/high,仅在confirmedReview时执行 |
| 不建议删除 | 一律跳过 | prohibited,清理引擎直接跳过 |
分级解决展示问题,真正关键的是扫描与删除的职责分离:扫描器只发现候选条目,产出JunkItem,不持有删除能力;删除由Cleaner执行,并在删除前重新检查文件是否存在、大小与修改时间、路径是否为符号链接、安全等级是否成立。
之所以要再检查一次,是因为扫描与确认之间可能隔了很久:文件可能被重写,目录可能被移动,路径中间的组件甚至可能被替换成指向受保护目录的符号链接。只判断一次覆盖不了这些变化,第 4 篇会详细讨论这条链路。
这些检查是现有的防护措施,能覆盖已经测试过的路径穿越、结果过期与符号链接替换场景,但不应被理解为对所有文件系统竞争条件的绝对安全保证。
按当前源码,功能状态大致如下:
| 功能域 | 状态 | 说明 |
|---|---|---|
| 系统与浏览器缓存扫描 | 已实现 | CacheScanner、LogScanner、CrashScanner、TempScanner;浏览器规则覆盖 Safari/Chrome/Edge/Firefox 缓存,不含 Cookies 与历史 |
| 开发者缓存 | 已实现 | developer.json33 条规则,覆盖 Xcode、Homebrew、Maven、Gradle、npm、pnpm、Yarn、CocoaPods、JetBrains、VS Code、Cursor 等常用工具 |
| Group Container 深扫 | 已实现 | 按容器内部角色拆分,只把缓存/临时/日志列为可重建数据 |
| 安全与清理链路 | 已实现 | 规则驱动安全等级、清理前复核、废纸篓/永久删除策略、逐项结果与历史 |
| 应用识别与管理 | 已实现 | 元数据、签名/架构、排序/筛选、App Storage 分解 |
| 存储趋势 / 增长 / 大文件 / 目录树 | 已实现 | 快照、增长分析、LargeFileScanner、FolderSizeAnalyzer |
| 磁盘健康与性能 | 部分实现 | 容量、健康分级、I/O、内存/Swap、APFS 快照、Spotlight、TRIM、优化建议;Top 活动进程未实现 |
| 历史、忽略列表、设置、国际化、增量扫描 | 已实现 | SQLite 持久化、SettingsStore、String Catalog、FileEntryStore |
| 卸载与遗留数据真实流程 / APFS 快照删除 / Docker prune | 有代码与单元测试,待真实环境验收 | 未在真实第三方 App 卸载、真实快照或 Docker 环境完成验收 |
| 启动项管理、深度/自定义扫描、文件类型分析、菜单栏工具与通知 | 未实现 | 启动项管理指登录项与 LaunchAgent/LaunchDaemon;应用自身开机启动已支持;菜单栏仅有显示窗口与退出 |
| UI 自动化测试、CI、公证、DMG | 未完成 | 见"当前工程限制" |
规划目标不等于已交付:启动项管理写在 V0.2.0 路线图里,源码中没有对应实现;Top 活动进程也未实现。
技术栈与选型
工程的最低支持版本为 macOS 14.0,Bundle Identifier 为com.pure.mac;以下技术选择都围绕这个工程的实际配置。
| 维度 | 选择 | 在项目中的职责与原因 |
|---|---|---|
| 语言 | Swift 6.0,SWIFT_STRICT_CONCURRENCY = complete | 并发任务较多,用于尽早暴露共享状态问题 |
| UI | SwiftUI + AppKit | 主界面用 SwiftUI;菜单栏、应用激活、Finder 定位用 AppKit |
| 持久化 | 系统 SQLite3(C API) | 保存历史、忽略、快照与扫描缓存;无 ORM,SQL 可控 |
| 工程 | XcodeGen(project.yml) | 目录变化后重新生成工程,减少手改pbxproj |
| 依赖 | 无第三方 Swift Package | 降低供应链与签名负担 |
| 系统能力 | Security、ServiceManagement、IOKit、CoreServices、OSLog、CryptoKit | 签名、开机启动、磁盘 I/O、Spotlight、日志与缓存指纹 |
几个系统框架的实际用途需要单独说明,避免"看到 import 就推断功能":
| 框架 | 实际用途 |
|---|---|
| Security | 通过SecStaticCode读取应用签名、Team ID、发布者 CN;不执行codesign子进程 |
| ServiceManagement | SMAppService.mainApp注册/注销开机启动 |
| IOKit / IOKit.ps | 读取IOBlockStorageDriver累计读写字节做 I/O 速率;读取电池信息 |
| CoreServices / CoreWLAN / SystemConfiguration | Spotlight 的"最后使用时间"元数据;Wi-Fi SSID 与网络接口枚举 |
| OSLog / CryptoKit / Charts | 统一日志;缓存 SHA-256 指纹;存储趋势图表 |
工程开启了complete检查,但仍有@unchecked Sendable+NSLock的共享类型;编译器在这些地方不再提供完整保证,第 3 篇会展开。
实际架构概览
实际代码采用更直接的分层:View → ViewModel → Engine → Scanner/Cleaner → 系统 API。架构规范设想的 Coordinator、UseCase、依赖注入容器没有落地,改用单例 Engine + ViewModel 编排;差异留到第 3 篇分析。
各层职责可以概括为:
- View:展示与操作,不直接删除文件或访问数据库。
- ViewModel:协调流程。
ScanViewModel负责扫描、清理、应用、历史与忽略;DiskHealthViewModel负责磁盘健康刷新。 - Engine:
ScanEngine并发编排并聚合结果;CleanEngine按风险策略执行并记录;UninstallEngine预检后复用清理链路。 - Scanner:只发现候选条目,输出
JunkItem;共享枚举逻辑,由RuleRepository与SafetyEngine判定安全等级。 - Cleaner:
TrashCleaner做通用清理;UninstallCleaner与GroupContainerCleaner用白名单限制范围。 - 安全校验:路径级判断在
SafetyEngine,多维评分在CleanupRiskScorer,删除前再复核。 - 持久化与缓存:
DatabaseManager存历史、忽略、快照与增长;FileEntryStore存扫描缓存,经ScanCacheSession注入并在扫描后提交。
典型流程是:ViewModel 构建应用上下文 →ScanEngine.quickScan并发调用扫描器 → 过滤忽略路径 → 聚合ScanResult→CleanupAnalyzer生成带风险等级的CleanupItem。清理时,选中的CleanupItem交给CleanEngine,由它决定执行、跳过或要求确认。
研发里程碑
由于当前目录不是 Git 仓库,无法得到提交级时间线。下面只列有证据的节点,并标明证据类型;文件修改时间只能说明"文件在某个时间被改动",不能当作功能完成日期。
| 节点 | 内容 | 证据类型 |
|---|---|---|
| 规划与规范形成 | 功能规划、架构规范、UI 规范、磁盘健康提示词等文档 | 文档记录 |
| 进度清单 v1.1 → v1.8 | 记录卸载、磁盘健康、风险模型、快照删除、按应用视图等增量 | 文档记录(文档标注 2026-09-15) |
| 2026-10-21 | 一次 15 项测试运行,覆盖CleanupAnalyzerTests,全部通过 | 仓库内xcresult解析 |
| 2026-11-03 | 全量测试、性能套件隔离重跑、Release Universal 构建 | 本次实际执行 |
| 版本 0.1.1 (6) | 对应已完成里程碑;按进度文档,V0.2.0 仍差启动项管理 | 工程配置 + 文档记录 |
这些证据只能说明项目达到了"可构建、可测试、核心链路闭环"的阶段,不足以支撑精确日期叙事;文中的"历史信息"均为文档记录,不是本次复现结论。
当前实现情况
先给出统计口径,再看数字:
| 指标 | 数值 | 统计口径 |
|---|---|---|
| 代码规模 | 173 个 Swift 文件 / 20,675 行 | 应用 13,692 行 + 测试 6,983 行,不含build/ |
| 测试套件 | 56 个 | XCTestCase子类数量 |
| 测试方法 | 388 个 | 静态扫描func test的数量,不等同于本次执行数 |
| 本地化键 | 623 个 | Localizable.xcstrings全部键;其中 620 个具备非空 en + zh-Hans 文案,3 个为纯格式串 |
| 规则 | 41 条 | Resources/Rules/四个文件:system 4、browser 4、developer 33、applications 0 |
| Release | Universal(x86_64+arm64),约 11 MB | lipo -info/du -sh;版本 0.1.1 (6),不是 DMG |
测试数据需要把事实与结论分开:
- 本次全量运行实际执行 388 项,387 通过、1 失败:
IncrementalScanPerformanceTests/testPerformanceFlat()报Test crashed with signal term,记录耗时 0 秒。 - 随后用
-only-testing单独运行IncrementalScanPerformanceTests,该套件的 2 项测试(testPerformanceFlat与testPerformanceNested)全部通过,耗时约 106 秒。 - 全量运行与隔离重跑针对同一工作区;测试开始后没有 Swift 源码改动,Release 构建也在同一代码状态下完成。
- 隔离重跑通过,但全量中断的具体原因尚未确认,不能归因于单一因素。
因此只能说"全量测试基线仍未稳定通过",不能说"测试体系已稳定";单次隔离成功不能替代可重复的全量结果。
当前工程限制
1. 缺少 Git 版本控制
当前事实:项目目录不是 Git 仓库,git log返回fatal: not a git repository;没有提交、分支或标签可查。
实际影响:无法回滚、定位回归或做提交级复盘;对两万行规模的项目,这比缺功能更影响长期维护。
后续改进方向:初始化 Git 仓库,先把当前状态作为基线提交并打标签,再让后续变更独立提交;配合 CI 建立最基本的回归门禁。
2. macOS 分发链路尚未完成
当前事实:本次实际构建出的 Release 产物是 Universal(x86_64+arm64),版本 0.1.1 (6),但签名是 ad-hoc,entitlement 中包含com.apple.security.get-task-allow = true,spctl -a -t exec判定为 rejected;仓库中没有公证、DMG 或安装验证的记录。
这些结论需要分开看:
- ad-hoc 签名意味着没有 Developer ID 身份,系统无法确认开发者;
- **
get-task-allow**是开发调试用的 entitlement,不应出现在对外分发包中; codesign --verify通过只说明签名结构完整,不代表具备 Developer ID 或已完成公证;spctlrejected是 Gatekeeper 评估失败的结果,通常需要 Developer ID 签名与公证才能通过。
实际影响:产物可在本机开发测试,但不能对外分发;把"能出 Universal App"当成"可以交付"是本次调查最需要避免的误判。
后续改进方向:配置 Developer ID、用正式证书签名并移除调试 entitlement、完成公证与 stapling、制作 DMG、验证安装/升级/卸载,再考虑分发渠道。
3. 全量测试基线仍需进一步验证
当前事实:388 项静态测试方法,本次全量运行为 387 通过、1 项被终止;隔离重跑 2 项通过,根因未确认。
实际影响:无法据此宣称"每次全量都全绿",也无法直接把全量测试当作 CI 的硬门禁。性能测试与功能测试混在同一 target,可能放大了资源压力。
后续改进方向:拆分性能测试 target 或增加超时/重试,记录失败时的资源与宿主日志;在 CI 中区分"功能测试必须全绿"与"性能测试单独跑"两条线。
系列文章导航
- 项目总览(本篇)
- 项目规划与技术选型
- Vibe Coding 与工程架构
- 核心功能实现与文件系统安全
- 国际化与 macOS 适配
- AI 生成代码的测试与质量控制
- 构建、签名与应用交付
- 项目复盘
完整事实底稿见 project-research.md,需要人工确认的事项见 FACT_CHECK.md。
小结
Pure for Mac 当前处于"核心安全链路闭环、功能面较广、交付链路未闭环"的阶段:核心链路有源码与测试支撑,也能产出 Universal 产物;但版本控制、签名公证、全量测试稳定性仍是明确缺口。
本篇建立背景与事实基线;后续将讨论规划、架构、文件系统安全、系统适配、测试、构建交付和整体复盘,以及 AI 辅助开发的实际作用。