首页
/ Mole 的 AGENTS.md / CLAUDE.md 深度解析:一份约束 AI 安全维护 macOS 清理工具的工程契约

Mole 的 AGENTS.md / CLAUDE.md 深度解析:一份约束 AI 安全维护 macOS 清理工具的工程契约

2026-09-04 12:10:19作者:温玫谨Lighthearted

Mole 是一个「删文件」的工具,而删错一个文件就可能毁掉用户数据——正因如此,它的维护过程本身必须被强约束。本文以仓库根目录的 CLAUDE.md(实际是 AGENTS.md 的符号链接)为骨架,系统拆解这份「AI 代理协作契约」如何定义产品边界、安全规则与验证流程,并结合 lib/core/bin/ 下的真实源码,说明其中每条规则背后的实现依据。读完你会掌握:如何在一份「删文件工具」仓库里,读懂并遵循其安全不变式、测试纪律与热点文件归属。

一、这份文档是什么:跨代理的「单一事实来源」

CLAUDE.md 开篇即声明自己是「任何在本仓库工作的 AI 代理(Claude Code、Codex 等)共享的单一事实来源(source of truth)」。仓库里的实际形态印证了这一点:

  • CLAUDE.md 是一个符号链接,指向 AGENTS.md(即仓库根目录同时存在两个文件,前者 lrwxrwxrwx ... CLAUDE.md -> AGENTS.md)。这样 Claude 与 Codex 读到的是同一份项目契约。
  • 机器级或个人化的覆盖配置应放在 AGENTS.local.md / CLAUDE.local.md,二者均被 gitignore,不进入版本库。
  • 项目本身是「shell + Go 双栈的 macOS 系统清理与优化工具」,文档反复强调:安全规则比速度更重要(safety rules matter more than speed)

这一设计值得单独强调:在一个会执行 rm 的工具里,「谁来改代码、改的时候必须守哪些规矩」被提升为与代码同等的交付物。文档不是给人看的 README,而是给自动化的 AI 代理(以及协作者)的执行手册。

二、产品方向:先把「不做什么」写清楚

2.1 Mole 的定位与职责

文档将 Mole 定义为「终端优先(terminal-first)的 macOS 维护工具包」,核心职责是帮助高级用户:检查可回收空间、删除已知安全的残留、安全卸载应用、运行有界(bounded)的维护任务、从 CLI/脚本/紧凑 TUI 查看健康状态。它不是通用的 Mac 控制中心、包管理器、后台监控器或 GUI 功能镜像。

「应该做」的清单(What Mole Should Do)聚焦于:

  • 让清理/卸载动作变得无聊(boring)、可审阅、有日志、受路径/应用规则保护、可 dry-run;
  • 面向用户的删除优先走「废纸篓」这一可逆路径;
  • clean/uninstall/purge/installer 只针对可回收文件、应用残留、可重建缓存、安装器产物和精确的已知清理目标;
  • analyze 保持为磁盘浏览器 + 即席清理面;
  • status 保持为紧凑只读健康面板 + 稳定的 JSON/NDJSON 自动化输出;
  • optimize 保持为「执行前可解释、无需真实授权即可测试」的有界维护任务;
  • 命令 UX 保持终端原生:短标签、稳定对齐、可预测快捷键、单屏摘要、可选下钻。

2.2 明确「不做」的边界

「不应做」清单(What Mole Should Not Do)是一份典型的负面约束,用来防止功能蔓延:

  • 不添加宽泛的系统修改、隐私重置、包管理、应用 bundle 补丁或设备管理功能;
  • 不修改第三方应用 bundle 内容、签名资源、用户文档、凭据、会话、活动数据库或活动开发工具状态;
  • 不添加后台代理、持久监控、通知、调度器、菜单栏行为或 GUI 式状态;
  • 不把残留匹配从「精确的 app/bundle 证据」放宽到「厂商级、TeamID 前缀、通用名或兜底通配符删除」——这条是整个安全模型的基石;
  • 不把 status 变成嘈杂仪表盘;
  • 不靠「加提示/偏好/输出模式」来覆盖每一个边界情况——新 flag、新环境变量、新配置键的权重等同一个新设置,只有当「没有单一默认值对所有人正确」时才通过,且必须先陈述并拒绝「用默认值修复」的替代方案。文档直言:「伸手去拧一个旋钮来闭合一个 issue,这里的默认失败模式,而非边缘情况。」

2.3 产品决策过滤器(Product Decision Filter)

在接纳一个新功能前,需在 PR/issue/review 里回答五个问题:

  1. 它是否明确属于 clean、uninstall、analyze、optimize、status、purge、history、installer、update、completion、touchid 或 remove?
  2. 它是否默认安全、破坏性处可预览、无需真实授权即可测试、能用一屏终端解释?
  3. 用户能否在 Mole 改变之前,验证将要改变什么?
  4. 目标数据是否在本地可重建、可丢弃,或有精确 app/bundle 证据支撑?
  5. 它是否更适合做成 Mole Mac UI、文档、一条警告,或一句明确的「不支持」?

答案是「否」或「不清楚」时,应当拒绝、收窄或搁置该功能,直到产品价值胜过它带来的表面面积。

三、仓库地图:契约如何映射到真实目录

文档的「Repository Map」把每个顶层目录的职责讲清楚,这些路径在仓库中均可一一对应:

  • AGENTS.md 是跨代理单一事实来源,CLAUDE.md 必须保持为它的符号链接。
  • .claude/skills/ 是项目技能的规范存放处;.agents/skills/ 存放供 Codex 发现的相对符号链接(仓库中可见 bugsmolerelease-flowrelease-notes 四个 -> 软链),不要维护复制出来的技能正文
  • .claude/agents/ 存放聚焦的 Claude 审查画像(仓库中有 safety-reviewer.mdbash32-portability-reviewer.md),它们必须从本文件读取当前契约,而不是复制冻结版本的安全/可移植性规则。
  • mole —— CLI 入口。它只是一个路由器:解析参数、渲染菜单、分发子命令。业务逻辑不属于这里。自更新在 lib/manage/update.sh,自卸载在 lib/manage/remove.sh;二者都是 source(而非 exec),因为交互菜单和更新横幅会进程内调用它们。VERSION= 保持在 mole 里,因为 install.sh 会用 sed 从本文件读出它(当前 mole 中即 VERSION="1.53.0")。
  • lib/core/ —— 共享 shell 安全、UI、文件操作、操作日志、应用保护逻辑,以及集中式超时常量(timeouts.sh)。
  • lib/core/app_protection_data.sh —— 只读 bundle ID 与模式数组,被 app_protection.sh 消费,只有数据、没有逻辑
  • cmd/analyze/ —— Go 磁盘分析 TUI。main.go 只做 bootstrap;model.go 持有类型与访问器方法;update.go 持有 Bubble Tea 的 Update 链。
  • tests/fuzz_corpus/ —— 属性测试语料,被 path_validation_fuzz.bats 消费。
  • scripts/ —— check/test/build/release 辅助脚本。audit_bundle_drift.sh 支撑月度 bundle 审计;audit_function_duplication.pycheck.sh 内对「同体异名」shell 函数做门禁(--list 可列出所有分组);每 PR 的性能由 tests/core_performance.bats 覆盖。
  • docs/SECURITY_DESIGN.md —— 路径校验 / 应用保护 / # SAFE 注解契约的设计文档。
  • SECURITY_AUDIT.md —— 安全审查笔记。

四、开发与验证命令

文档给出的命令集(bash)如下,其中 MOLE_TEST_NO_AUTH=1 是贯穿始终的「测试不触真实授权」开关:

./scripts/check.sh --format
MOLE_TEST_NO_AUTH=1 ./scripts/test.sh
MOLE_TEST_NO_AUTH=1 bats tests/clean_core.bats
MOLE_DRY_RUN=1 ./mole clean
MOLE_TEST_NO_AUTH=1 ./mole clean --dry-run
MOLE_TEST_NO_AUTH=1 ./mole purge --dry-run
MOLE_TEST_NO_AUTH=1 ./mole installer --dry-run
find bin lib -name '*.sh' -print0 | xargs -0 -n1 bash -n
make build
go test ./...

文档补充了一条命名约定:公开文档与示例应优先使用已安装的 mo 命令;在仓库内验证源码树行为时才用 ./moleanalyzeanalyse 两种拼写都被接受。

这些命令在 Makefile 里有对应封装:make checkmake formatmake testmake test-gomake verify。其中 make verify 刻意只跑 check + Go 测试(见 Makefile 的 verify: check test-go);涉及有风险的清理/卸载/发布工作前,要用完整 Bats 套件

五、关键安全规则:删除漏斗与 # SAFE 契约

这是全文技术密度最高的部分,也是理解 Mole 安全模型的核心。

5.1 删除必须走安全助手,rm -rf 需逐行注解

文档要求:删除一律经由 lib/core/file_ops.sh 里的安全助手路由。裸 rm -rffind -delete 只有在同一行带有 # SAFE: <一句话理由> 注解时才允许——这正是 docs/SECURITY_DESIGN.md 中 Layer 2 定义、并由 .github/workflows/test.yml 强制执行的契约。

这一点在 CI 里有实打实的落地:.github/workflows/test.ymlgrep -rn "rm -rf" lib/ bin/ install.sh molegrep -v 掉带 # SAFE 注解或已走 safe_remove 的行,一旦发现「无注解的 rm -rf」即报错退出。也就是说,「安全注解」不是口头约定,而是 CI 里可执行的正则门禁。自建的 mktemp 文件对直接 rm -f 使用同样的注解;不要把临时工作路径送进 mole_delete,否则会给临时文件加上废纸篓路由和一条操作日志。

5.2 mole_delete:统一的删除漏斗

文档要求用户可见的清理统一走 lib/core/file_ops.shmole_delete,以保证「废纸篓路由、操作日志、dry-run 行为、路径保护」始终一致。源码印证了这套语义(mole_delete 定义于该文件 L2021 起):

  • 通过 MOLE_DELETE_MODEpermanent 默认 / trash)决定删除方式,非法值会记日志并 return 1
  • MOLE_DRY_RUN=1 只记录意图、不真正删除;
  • 校验委托给底层 safe_* 助手(内部调用 validate_path_for_deletion);
  • 特权删除若检测到「可被调用用户篡改的祖先目录」,会 fail-closed 并记 mutable-parent,拒绝继续(对应 L2058 起的 _mole_privileged_path_has_mutable_ancestor 分支);
  • 每次调用都向删除日志追加制表符分隔行:<iso_ts>\t<mode>\t<size_kb>\t<status>\t<path>,且 du 量不出大小时记 unknown 而非 0KB,避免事后取证把「测到零」与「测量失败」混淆。

文档还强调:在预期可恢复的场景(尤其 analyze 驱动的即席清理),把面向用户的清理路由进废纸篓

5.3 受保护路径与不可触碰清单

  • 绝不修改 /System/Library/Applecom.apple.* 等受保护路径;
  • 除非任务明确针对授权行为,否则绝不让验证阻塞在 sudo、AppleScript 或 macOS 授权提示上;
  • 绝不自动删除 Software Update 拥有的暂存树,如 /Library/Updates/macOS Install Data——目录年龄、进程列表、Software Update plist 状态都无法证明这些树在「扫描到删除」的时间窗内保持非活动,故保持只读;
  • 绝不删除/截断/vacuum 活动的 PowerLog 数据库/private/var/db/powerlog/.../CurrentBackgroundProcessingDB.BGSQL 及其 -wal/-shm 伴生文件)——大小和 mtime 无法证明 Apple 已关闭全部 SQLite 连接;
  • 绝不让基于特权的路径删除/移动经过「调用用户可篡改的祖先目录」safe_sudo_removesafe_sudo_find_deletemole_delete 在这些位置必须降级或 fail-closed;特权的废纸篓移动必须先跨入 /Library 下专用、不可变、root 所有的暂存区,再由调用用户把物品移入废纸篓。

5.4 安装与更新的 fail-closed 纪律

  • install.sh 在验证失败时保持 fail-closed:校验和/证明失配即中止并说明原因,绝不降级为源码构建(那会把「二进制被篡改」变成一条验证更弱的更安静路径);解析不到 release tag 而回退到 main 时必须警告这是「nightly 源码安装」。tests/install_checksum.bats 用中止用例把这两点钉死。README 里的安装 URL 保持不固定的 main:在那里固定 tag 会挡住修复到达新安装。
  • 一个会拒绝的门禁必须点名它命中了哪个原因、下一步该跑什么acquire_install_lock 通过 INSTALL_LOCK_FAILURE 报告稳定原因,不安全祖先变体用 INSTALL_LOCK_UNSAFE_ANCESTOR_REASON;保持「一行事实原因 + 一行按原因定制的下一步」,新加的更靠前门禁至少要与被它替代的失败一样可操作;钉死原因码路由而非笼统文案。
  • mo update 的自愈兜底(_update_self_heal_reinstall)之所以存在,是因为本地 bootstrap(临时文件、registry、exec)冻结在用户机器上,损坏的已装版本无法自修复(#1297)。它要求:把 install.shmain 直接流式送进 bash、不落地本地临时文件;稳定成功要断言「已装二进制的有界版本响应」而非安装器输出(V1.47.1 那种假成功形态);更新要按安装目录单飞(single-flight),让 receipt、commit 元数据与二进制校验不能跨并发代交叉——两个写者取同一个 target 邻近互斥锁,优先绝对路径 /usr/bin/lockf(内核即使持锁进程被杀也会释放该锁);lockf 只随较新 macOS 附带,所以强制它会在一堆旧发行版上、写文件前就退出(#1348),缺它时二者都回退到锁目录里的原子 mkdir。文档特别警告:不要把该 wrapper 做成 shell 数组——空的那个是回退路径,而空数组在 set -u 下、在 macOS 自带的 bash 3.2 上会触发未绑定变量错误。回归测试位于 tests/update.batstests/install_checksum.bats

六、工作规则:去重、孤儿检测与清理分类学

文档的「Working Rules」是一条条从事故与审计中沉淀的细则,信息密度极高。择要如下:

  • should_protect_path() 优先:新增任何清理行为前,先查 lib/core/app_protection.shshould_protect_path()(源码 L355);新增应用缓存/卸载/残留清理前,先查应用保护助手。bundle 保护匹配是大小写敏感的 globbundle_matches_pattern,源码 L69),且 macOS 系统 bundle 在不同版本间报告的大小写不一致(macOS 26 同时下发 com.apple.bootcampassistant 与旧式 com.apple.BootCampAssistant)。当月度 bundle 漂移审计报告缺口时,要按审计打印的样子补上精确 ID,并在评估严重度前检查运行时的 com.apple.* 兜底保护。
  • 按「恢复契约」而非目录名/下载成本来分类清理:Go 模块缓存有属主文档、机器可读、可独立白名单化,故通过 go clean -modcache 重置;但 registry/src、Cargo git$DENO_DIR~/.ivy2/cache~/.m2/repository~/.nuget/packages~/.cabal/packages~/.cpan/sources 这类「直接消费或混合状态」的存储仍然保留。下载类模型/实验根(~/.cache/huggingface~/.cache/torch~/.cache/tensorflow~/.cache/wandb)与工具链载荷(~/.sbt/boot~/.sbt/launchers~/.stack/programs)不走宽泛删除路径。
  • 一个 purge 目标永远不是容器is_project_container 会拒绝任何 basename 落在 MOLE_PURGE_TARGETS 里的项(而非另维护一份包目录清单)。否则一个游离的 ~/node_modules 会在其第一个包的 package.json 上命中「容器探测」,每个包都变成项目根,扫描从产物下方开始,filter_nested_artifacts 永远看不到父级可折叠,于是包内的 dist/build/ 到达删除列表——删完只剩 package.json,npm 报「树是最新的」,恢复还得 npm ci,而这正是 purge 承诺绝不需要的网络恢复(#1459)。vendor/Pods/ 同形,所以规则就是目标清单本身而非手写的三个名字。lib/clean/project.sh 里有三个扫描根入口:维护者默认清单、用户配置文件、发现结果的消费者——所以这一处探测就是全部表面。由 tests/purge.bats 里两个 #1459 用例锁定。
  • 别加 shell 侧目录大小缓存:APFS 不会把 mtime 向树上传播,父目录 mtime 在后代增删时不变,缓存会给用户一个过期的可回收数字。每次都量;get_path_size_kb 已经带超时。
  • 按「体与目的」而非名字判重scripts/audit_function_duplication.py 对归一化后的函数体做哈希、对新「同体」分组做门禁,包括 grep 扫不出来的改名拷贝。它找不到两个「写法不同却复现同一决策」的助手,所以要搭配「调用方 + 目的」扫描一起用。
  • 测试孤儿(test-orphan)模式:判定一个符号是死的之前,先在 libbincmdscriptstests 与顶层入口/安装脚本里 grep;检查 evaldeclare -fcompgen 的动态查找;删除后再 grep 一遍;追踪被删助手写入的变量与配置。测试本身不是生产调用方,子代理报告只是线索而非判决。
  • mole_clean_process_guard 是探针三态的唯一翻译器0 运行中、1 不在、2 无法判断;状态 2 必须拒绝。任何把 2 折进「未运行」的副本,都会在一个其他副本审阅时仍读得通的情况下,删掉一个仍在运行应用的文件。该函数位于 lib/core/base.sh(L1409 起)。
  • declare -f 探针到 bin/ 是一个共享 shim,绝不是一文件一拷贝:问 safe_clean_guardeddefer_cleanup_family 是否存在,等于问 bin/clean.sh 是否被加载——生产环境总在,独立 Bats 用例里从不在。用 mole_defer_cleanup_family,或直接调用 safe_clean_guarded 让测试提供它;不要把 _safe_clean_impl 抬进 lib/core/,因为许多测试刻意替换 safe_clean,绕过那个缝会把断言变成 fixture HOME 下的真实删除尝试。

七、热点文件归属(Hotspot Ownership)

文档专门列出「故意就大、不要一上来就拆分」的文件,要求编辑保持窄、保留局部安全边界、触碰某区域时跑对应测试。这些归属在仓库里均可对应:

  • lib/clean/user.sh 拥有用户级清理流、浏览器缓存、云/应用支持清理、设备固件、Apple Silicon 缓存。Chrome/Edge/Brave 旧版本清理是一个表驱动助手 _clean_chromium_old_versions 加三个薄公共 wrapper;wrapper 名是测试表面,要保留。clean_edge_updater_old_versions 被刻意排除在外:它只修剪严格旧于已装 Edge 的分阶段更新载荷,无 Current 符号链接,从不升级到 sudo 删除——合并进去会悄悄改变其语义。
  • lib/core/app_protection.sh 拥有卸载/数据/路径保护策略与 bundle 匹配;app_protection_data.sh 拥有受保护应用类别清单。
  • lib/clean/project.sh 拥有 purge 发现、项目产物过滤、purge 菜单与 purge 配置。
  • bin/uninstall.sh 拥有卸载命令编排、应用清单、元数据刷新、list/json 输出。
  • lib/uninstall/batch.sh 拥有批量卸载执行、共享 bundle ID 兄弟守卫、launch service 与登录项拆除、brew cask 删除路由。
  • lib/clean/dev.sh 拥有开发工具清理、语言/工具链缓存、AI agent 缓存、Codex 运行时处理。
  • lib/clean/app_caches.sh 拥有逐应用缓存清理与 Autodesk Fusion 旧 bundle 修剪器。Fusion 删的是整个 bundle,所以要保留完整证据链:40 位十六进制目录、恰好一个 com.autodesk.fusion360 bundle、更旧的 CFBundleVersion、元数据工作前后属主复查、通过 safe_remove 的最终身份绑定。
  • lib/optimize/tasks.sh 拥有 optimize 任务注册与系统维护动作。
  • bin/clean.sh 拥有 clean 命令编排、section 输出与安全清理执行。section 输出遵循一个固定节奏:标题 → loading 态 → 内容 → 一个尾随空行。_safe_clean_impl 会在昂贵的策略探针前先跳过当前不存在的目标,再在咨询 dry-run 守卫或注册预览前过滤受保护、白名单与编译模型目标;每个存活目标都在其动作边界被重新校验,从而预览与真实清理保持同一合格集。
  • lib/manage/update.sh 拥有自更新、registry/bootstrap 替换、自愈兜底。保留 fail-closed 版本检查。
  • cmd/analyze/update.go 拥有 Bubble Tea 的 Update 链与消息处理器(Init、scanCmd、updateKey、goBack、switchToOverviewMode、enterSelectedDir),是 cmd/analyze/ 里最大的文件,也是新键绑定/消息类型/导航行为的自然落点;main.go 只做 bootstrap;model.go 持有类型与 model 结构体。
  • cmd/analyze/cache.go 拥有 analyze 缓存 schema、过期、load/save、失效与可缓存性决策;计算变更必须在同一变更里使过期的持久化数据失效
  • lib/core/file_ops.sh 拥有删除漏斗、废纸篓/永久路由、操作日志结果、大小记账与最后一路径校验;lib/core/base.sh 拥有共享 shell 原语与 source 顺序敏感的 section 助手。策略留在现有保护助手里,不要新增第二条删除路径
  • cmd/analyze/scanner.go 拥有磁盘遍历、Spotlight 集成、取消与全部扫描并发预算;把它的信号量当作相互独立的资源限额,改动前先测量。
  • lib/clean/apps.sh 拥有应用数据清理、孤儿服务发现与狭窄的「已验证容器桩」例外;lib/clean/hints.sh 是只读指引,必须保持有界、超时感知、非破坏。
  • lib/ui/menu_paginated.sh 拥有共享的 Bash 3.2 兼容选择 UI 与终端恢复;保留 trap 链、TTY 恢复与空选择行为。
  • cmd/status/view.go 只拥有 status 渲染;采集与 JSON/NDJSON 契约在 cmd/status/ 其他地方。
  • bin/installer.sh 拥有安装器发现、不可变删除计划校验、分页选择流与不完整清理的退出语义。

八、验证流程:别让「假绿」蒙混过关

文档的「Verification」部分几乎全是「如何避免测试假绿」的血泪经验:

  • Shell 变更:先 ./scripts/check.sh --format,再跑相关 Bats 或 MOLE_TEST_NO_AUTH=1 ./scripts/test.sh;Go 变更:go test ./...;清理行为:先 dry-run 或测试模式。
  • 要读套件自己的汇总行,绝不用你臆造的数字scripts/test.sh 把时序敏感的文件拆成串行 Bats 运行,其 TAP 输出与主并行批次不同,只数一个输出前缀会低估完整套件。裁判是测试运行器的汇总与被捕获的退出状态。
  • 要带着 $TERM 跑套件。后台化的 ./scripts/test.sh 没有 TTY,tput 失败,bats 校验器在半路死于断开的管道,留下截断日志与非零退出,看起来像一片红。TERM=xterm-256color MOLE_TEST_NO_AUTH=1 ./scripts/test.sh 能跑完;把这一次归类为「环境问题」而非「产品失败」。
  • 一次 cancelled 的 CI 运行不等于通过。每个 workflow 对 ${{ github.workflow }}-${{ github.ref }} 设了 cancel-in-progress: true,所以 main 上后来的 push/merge 会取消仍在为旧 commit 运行的检查。要对着「当前包含该变更的 sha」验证,读 --json status,conclusion 而非颜色。
  • 绝不把测试、检查或 CI 管道进 tail/head。管道报告的是分页器的退出码,于是红色运行读起来是绿色。要么完整打印,要么落到文件再单独检查状态。
  • [[ ... ]]run ... /bin/bash <<'EOF' heredoc 里可能什么都没断言:后面某条成功命令能让内层脚本返回零。让有意义的 heredoc 内断言以 || exit 1 收尾,或打印值再在 Bats 的 $output 上断言。每个守卫测试都必须在「修复前路径」观察到红、「恢复后」观察到绿。
  • golangci-lint 报告来自已删除临时 worktree 或不存在的 path,清本地缓存重跑:
golangci-lint cache clean
golangci-lint run ./cmd/...

九、发布流程(Release)

文档把发布收敛为一条铁律:基于大写 V tag 推送触发的 release.yml 驱动流程。完整发布 runbook(分发渠道、前置清单、tag/发布命令、精选笔记交接、发布专属陷阱)放在 .claude/skills/release-flow/SKILL.md,任何「发布风」任务开始前先读它;笔记格式归 .claude/skills/release-notes/SKILL.md 管。始终适用的一条:一个发布风运行将触碰哪些分发渠道,要重新陈述并与维护者确认;渠道范围由维护者指定,绝不由 AI 推断

十、结语:把「安全」写成可执行的契约

CLAUDE.md 当作一份普通文档会严重低估它的价值。它把「删文件工具最怕的是什么」逐条翻译成了可验证的工程约束:裸 rm -rf 必须带 # SAFE 注解且被 CI 正则门禁、删除统一走 mole_delete 漏斗并 fail-closed、bundle 匹配大小写敏感且需精确证据、purge 目标永不是容器、测试不能假绿、发布渠道必须由人指定。配合 docs/SECURITY_DESIGN.md 的分层设计、.github/workflows/test.yml 的强制检查与 SECURITY_AUDIT.md 的审计笔记,这份契约构成了 Mole「安全优先于速度」的完整闭环——对任何需要让 AI 代理安全地维护一个「会删东西」的仓库的团队,它都是一份值得参考的范本。

登录后查看全文
热门项目推荐
相关项目推荐