关于 agile-tdd
agile-tdd 是面向软件开发 Agent 的测试驱动开发流程技能,指导按 Red-Green-Refactor 编写测试并选择测试层级。它还提供可选钩子模板,用于对源文件缺少配套测试的情况发出警告或阻止写入。
主要功能
- 01引导 Red-Green-Refactor 循环
- 02按行为选择单元、集成或端到端测试
- 03规定测试命名与文件布局
- 04提供覆盖率目标和测试反模式
- 05可选钩子检查源文件配套测试
- 06支持 warn 或 block 执行模式
适用场景
- 01为新功能规划 TDD 测试
- 02为现有模块补充测试
- 03判断功能适合的测试层级
- 04为项目配置测试文件护栏
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ djalmajr/ skills --skill agile-tdd安装后在 Claude Code 中输入/agile-tdd确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
templates/agents-block.md.tmplopencode-plugin.js.tmpltdd-guardrails.yml.tmpltemplates/hooks/tdd-announce.sh.tmpltdd-pre-write.sh.tmpltdd-session-audit.sh.tmpltemplates/lib/audit-helpers.sh.tmpltemplates/project-types/README.mdtemplates/project-types/desktop/README.mdtemplates/project-types/mobile/README.mdtemplates/project-types/pwa/README.mdtemplates/project-types/tauri/agents-block.partial.mdaudit.partial.shdetect.shguardrails.partial.ymlREADME.mdtemplates/project-types/tauri/hooks/tdd-record-mcp.sh.tmpl详细介绍
TDD(测试驱动开发)
引导 Red-Green-Refactor 循环和务实的测试策略。“编写测试。不必太多。主要写集成测试。”
通过斜杠命令收到的初始上下文:$ARGUMENTS
如果 $ARGUMENTS 不为空(例如模块名称、功能描述),请以此为起点。
如果为空,请询问要测试什么。
语言
使用用户的语言编写产物和测试描述。如有疑问,请询问。测试代码本身(函数名、断言)保持英文。
项目根目录
此技能会在相对于项目根目录(开展工作的仓库)的路径下编写产物,而非 Agent 当前工作目录。
- 如果从项目内部调用,请使用此技能中列出的相对路径。
- 如果从其他目录调用(例如同级仓库,或项目位于其他位置),请在每个产物路径前加上
<project-root>/。 - 如果项目根目录不明确,请在写入前通过 harness 的提问工具向用户确认。
提问
遵循 CLAUDE.md / AGENTS.md 中的项目级约定(“技能提问约定”)。在以下决策点使用 harness 的结构化提问工具——AskUserQuestion(Claude Code)、ask_user_question(Codex)或 question(OpenCode)。
| 决策点 | 采用结构化提问的原因 | 建议选项 |
|---|---|---|
| 强制模式(安装时) | 难以撤销的策略选择 | 警告 · 阻止 · 保持当前设置 |
| 测试策略(存在歧义时) | 影响文件布局 | 同级文件 · 同级目录 · tests 根目录 |
| 豁免特定路径 | 修改防护配置 | 是 · 否 · 稍后审核 |
自由文本提示(不使用结构化工具):
- 测试描述
- 豁免理由
无暂停模式:如果用户明确禁用了技能执行过程中的澄清,则将每个结构化提示转换为 待确认问题(或等效内容)中的条目,并继续执行,不要暂停等待回复。
适用场景
- 使用 TDD 开始开发新功能
- 为现有代码添加测试
- 为模块建立测试覆盖率
- 不确定某项内容需要单元测试、集成测试还是 E2E 测试
不适用场景
- 测试无益的快速原型——使用
/agile-proto - 一次性脚本
- 纯文档修改
TDD 循环
- Red(红)——编写一个描述预期行为的失败测试
- Green(绿)——编写使测试通过的最少代码
- Refactor(重构)——在不改变行为的前提下改进结构
- 重复
明确展示每个步骤。不要跳过 Red——测试必须先失败。
测试金字塔(务实版)
| 层级 | 目标占比 | 重点 |
|---|---|---|
| 单元 | 60% | 纯函数、转换器、工具函数 |
| 集成 | 30% | 服务、数据库交互、API 路由 |
| E2E | 10% | 关键用户流程 |
整体覆盖率目标:75% 以上。
对于前端工作,应将这些比例视为风险参考,而非配额。优先编写能够覆盖用户行为、验证、本地状态、API 契约、权限、离线/同步行为和关键流程的集成测试。避免只断言静态文本、按钮是否渲染,或设计系统组件的实现细节的测试。
如果项目将业务规则保存在 planning/<initiative>/business/*.md 中,请使用这些规则 ID 判断哪些内容值得测试。测试应验证重要规则背后的行为,而不是复述规则文本。
文件结构
- 单元: 与源文件放在一起(
foo.test.ts与foo.ts并列) - 集成/E2E: 使用
tests/,并包含integration/、e2e/、helpers/、fixtures/、mocks/ - 命名:
.test.ts(单元/集成),.e2e.test.ts(E2E) - 绝不使用
.spec.ts
规则
- AAA 模式(Arrange / Act / Assert,即准备 / 执行 / 断言)
- 每个测试只验证一个概念
- 使用读起来像句子的描述性名称
- 始终使用工厂(例如
faker),避免使用硬编码数据 - 使用
beforeEach隔离测试——测试之间不得共享状态 - 测试行为,而非实现细节
反模式(应避免)
- 相互依赖的测试(测试 A 依赖测试 B 先运行)
- 随意使用
sleep(ms)——应使用适当的等待方式 - 测试私有方法——应通过公共 API 测试
- 在测试中使用
console.log——应使用适当的断言 - 依赖执行顺序的测试
- 模拟自己编写的代码(模拟外部依赖,而不是自己的代码)
覆盖率目标(细分)
| 区域 | 目标 |
|---|---|
| 转换器 / 纯函数 | 90%+ |
| 工具函数 | 85%+ |
| 服务 | 80%+ |
| 路由 / 处理程序 | 70%+ |
命令(Bun)
bun test
bun test --watch
bun test --coverage
bun test --filter "name"
bun test src/dir/
根据需要调整为其他运行时(vitest、jest)。建议命令前,先从 package.json 或配置文件中检测项目使用的测试运行器。
流程
1. 明确测试内容
浏览代码,了解:
- 哪个模块或功能需要测试
- 哪些行为至关重要
- 已覆盖哪些内容(检查现有测试)
- 此次更改必须满足哪些业务规则 ID、验收标准或原型流程
对于前端工作,在开始 Red 阶段前,先找出所有实际存在的原型来源。项目可能有 Agile-Proto 浏览器原型、Agile-Design 设计工具原型、两者都有,或两者都没有。原型证据有助于选择组件并明确可观察行为;它不会授权或阻止实施。
Agile-Proto 来源
在项目中已确定的位置查找浏览器原型,例如 planning/*/proto/ 和 {app}/client-proto/。读取其稳定的场景 ID / 路由,并检查实际的 htm-ui/<module>.js 导入。这些导入是直接的组件证据:
htm-ui/button.js对应维护中的 HTM UI Button 模块;- 原型专用的组合文件属于组合,而不是复制来的基础组件目录;
- 未导入维护中组件的自定义标记属于尚未解决的映射警告,而不是停止工作的理由。
使用原型中可观察到的行为和路由流程作为交互证据。根据目标应用已安装的组件系统和仓库惯例,确认生产环境中的对应实现,而不是机械地复制仅用于原型的标记。
Agile-Design 来源
阅读 planning/<initiative>/design/README.md(原型索引)及其总结的配套说明。屏幕和状态 ID、触发条件、操作目标和可见规则都是测试的行为证据。设计文件本身仅供视觉参考:它没有从设计到代码的组件映射,因此组件选择应依据目标应用已安装的组件系统和 /design-workflow。
两种来源都存在时
为目标用户故事或屏幕建立合并后的来源映射:
- 根据稳定的规划 / 用户故事 / 需求 ID 以及屏幕 / 场景用途进行匹配;
- 使用 Agile-Design 说明了解状态、转换和可见规则;
- 使用 Agile-Proto 导入和运行时交互了解浏览器行为及 HTM UI 标识;
- 任一来源映射到已安装的生产组件时,优先使用该组件;
- 来源不一致时,发出警告,并选择最贴近目标验收标准和当前产品代码的来源。只有当分歧会实质性改变用户可见行为或范围时,才询问用户。
绝不要仅仅因为原型缺失、不完整、过时或以多种格式呈现就拒绝实施。AI 应利用所有可用信号,在有帮助时说明判断的可信度,并依据最充分的证据选择组件后继续推进。
TDD 仍以可观察行为为准:测试屏幕流程、验证、权限、状态变化和集成契约,而不是设计系统组件的内部标记。
2. 选择合适的测试类型
以测试金字塔为指导:
- 没有副作用的纯函数?单元测试。
- 与数据库或外部 API 通信的服务?集成测试。
- 跨多个系统的关键用户流程?端到端测试。
- 涉及验证、API 契约、权限、乐观更新或离线/同步状态的前端行为?集成测试。
- 静态文案、简单渲染或没有规则的纯视觉细节?通常无需测试,除非测试能防止已知回归。
对于本地优先产品,优先编写覆盖命令验证、乐观状态、离线队列持久化、协调、冲突处理、权限和审计事件的测试。
3. 执行 TDD 循环
针对每种行为:
- 编写失败的测试(Red)
- 编写最少量的实现代码(Green)
- 按需重构
- 验证测试仍然通过
如果有助于后续完善,可在测试描述或相关故事文档中记录业务规则 ID 或验收标准。
4. 验证覆盖率
运行覆盖率检查并对照目标。优先填补关键领域的覆盖缺口。
衔接
- 实现功能期间:在
/agile-story检查清单中开展工作 - 实现完成后:使用
/agile-refinement审查测试质量 - 关闭之前:确保测试纳入
/agile-status(关闭模式)验证 - 如果 TDD 工作流暴露出反复出现的阻碍、缺失的指导、薄弱的模板或不清晰的验证方式,请记录一条简明的技能反馈说明,注明受影响的技能/模板、证据、建议的修改和验证材料。
- 如果反复出现的 TDD 阻碍表明需要修改技能/模板,请先起草提案供人工审查,再修改流程库。
强制执行(可选,按项目启用)
除了提供建议外,此技能还附带钩子模板,可将 TDD 规则转化为项目级防护措施。项目启用后,每次实现会话都会在文件写入层面接受检查,无需 Agent 记得调用此技能。
强制执行的内容
Write|Edit|MultiEdit上的 PreToolUse — 如果目标文件符合.tdd-guardrails.yml中的source_paths,且不存在对应测试,钩子会发出警告(mode: warn)或阻止工具调用(mode: block)。- Stop 钩子 — 在会话结束时扫描 git diff,并报告有修改但没有对应测试的源文件。
- SessionStart 钩子 — 提示“已启用 TDD 强制执行”,让 Agent 知晓规则正在生效。
钩子模板位于 skills/agile-tdd/templates/hooks/*.sh.tmpl,配置架构位于 skills/agile-tdd/templates/tdd-guardrails.yml.tmpl。
配置(.tdd-guardrails.yml)
| 键 | 含义 |
|---|---|
enabled | 全局开/关 |
mode | warn(仅输出到 stderr)或 block(PreToolUse 拒绝调用) |
source_paths | 必须有对应测试的 glob 模式 |
test_strategy | sibling(foo.ts → foo.test.ts)、sibling_dir(__tests__/foo.test.ts)或 tests_root(<app>/tests/integration/foo.test.ts) |
exemptions | 允许没有测试的 glob 模式(入口点、生成文件、UI 基础组件) |
**模式语义:**钩子脚本使用 bash case glob,而非扩展 globstar。在 bash case 模式中,* 匹配包括 / 在内的任意字符序列;不存在 **。因此,apps/*/src/*.ts 同时匹配 apps/server/src/handler.ts 和 apps/server/src/auth/handler.ts。不要在 source_paths 或 exemptions 中使用 **。
强制执行的注意事项
钩子会检查文件对是否存在,但不会也无法验证:
- 测试是否在源代码之前编写(不会检查 Red-before-Green 顺序)。
- 测试是否确实覆盖源代码(不会进行语义匹配)。
- 测试当前是否通过(不会运行测试)。
语义层面的规范(每个测试覆盖一种行为、优先使用工厂而非硬编码数据、使用描述性名称、遵循 AAA)仍由 Agent 负责。钩子只是防护措施,并非保证。
手动安装(在 tdd-init 脚本推出之前)
各运行环境的操作方式有所不同——Claude Code 和 Codex 会直接运行 shell 钩子;OpenCode 则运行一个 JS 插件,由它来编排相同的 shell 脚本。
-
将
templates/tdd-guardrails.yml.tmpl复制到<project-root>/.tdd-guardrails.yml,并编辑source_paths和exemptions,使其符合仓库布局。然后运行项目类型检测器,以填充
project_types:for type in .claude/skills/agile-tdd/templates/project-types/*/; do name="$(basename "$type")" [ -f "$type/detect.sh" ] || continue bash "$type/detect.sh" "$PWD" && echo "detected: $name" done对于每种检测到的类型,将其
guardrails.partial.yml追加到新建的.tdd-guardrails.yml中(如果该区块已存在,则进行合并),并将类型 slug 添加到project_types列表中。 -
复制钩子模板。从
templates/hooks/复制到<project-root>/.claude/hooks/、<project-root>/.codex/hooks/、以及<project-root>/.opencode/hooks/(OpenCode 插件会通过node:child_process.spawn调用相同的脚本)。移除.tmpl后缀,并运行chmod +x。还要复制共享辅助文件:
templates/lib/audit-helpers.sh.tmpl → .claude/hooks/lib/audit-helpers.sh以及项目类型目录:
templates/project-types/ → .claude/hooks/project-types/会话审计脚本会在这两个位置查找。Codex/OpenCode 也应分别镜像到
.codex/hooks/和.opencode/hooks/下。 -
在各运行环境的配置中注册钩子:
- Claude Code(
.claude/settings.json):添加一个匹配Write|Edit|MultiEdit、调用$CLAUDE_PROJECT_DIR/.claude/hooks/tdd-pre-write.sh的PreToolUse条目,一个调用tdd-session-audit.sh的Stop条目,以及一个调用tdd-announce.sh的SessionStart条目。与现有钩子合并——不要替换。 - Codex(
.codex/hooks.json):添加匹配apply_patch|Edit|Write|MultiEdit的PreToolUse条目,以及Stop和SessionStart条目。命令形式使用bash "$(git rev-parse --show-toplevel)/.codex/hooks/<script>.sh"(Codex 模式)。每个条目都包含statusMessage字段。 - OpenCode:将
templates/opencode-plugin.js.tmpl复制到<project-root>/.opencode/plugins/tdd-guardrails.js。该插件订阅tool.execute.before(相当于 PreToolUse)、session.created(相当于 SessionStart)和session.idle(最接近 Stop——审计 shell 通过临时状态文件实现幂等,因此多次触发也安全)。插件通过node:child_process.spawn启动相同的.opencode/hooks/tdd-*.sh脚本。OpenCode 不会直接调用 shell 脚本;插件是入口。
- Claude Code(
-
将
templates/agents-block.md.tmpl的内容追加到AGENTS.md和CLAUDE.md,告知 Agent 项目已启用 TDD 强制检查。对于每种检测到的项目类型,还要将其
templates/project-types/<type>/agents-block.partial.md追加到相同的 文件中(保留/ :end标记,以便重新安装时能原位更新)。 -
在
.claude/settings.json中注册特定类型的匹配器:- 对于
tauri:添加一个匹配mcp__tauri__webview_screenshot|mcp__tauri__webview_execute_js|mcp__tauri__webview_dom_snapshot|mcp__tauri__manage_window并调用$CLAUDE_PROJECT_DIR/.claude/hooks/tdd-record-mcp.sh的PostToolUse条目。
Codex 对应的配置放在
.codex/hooks.json中;对于 OpenCode, 订阅按工具名称筛选的tool.execute.after,并通过node:child_process.spawn启动相同的 shell 脚本。 - 对于
这些钩子是防护措施,并非保证——它们检查的是文件对是否存在,而不是测试质量。语义层面的规范(每个测试只验证一种行为、优先使用工厂而非硬编码数据)仍由 Agent 负责。
运行环境兼容性矩阵
| 运行环境 | 入口点 | 写入前事件 | Stop 等效项 | 会话开始 |
|---|---|---|---|---|
| Claude Code | .claude/settings.json hooks | PreToolUse(匹配器 Write|Edit|MultiEdit) | Stop | SessionStart |
| Codex | .codex/hooks.json hooks | PreToolUse(匹配器 apply_patch|Edit|Write|MultiEdit) | Stop | SessionStart |
| OpenCode | .opencode/plugins/tdd-guardrails.js JS 插件 | tool.execute.before | session.idle(最接近的可用事件;审计具有幂等性) | session.created |
有意绕过
- 针对某个路径:将其添加到
.tdd-guardrails.yml → exemptions。 - 针对某个会话:临时设置
enabled: false(并在提交前恢复)。 - 切勿为了让钩子静默而删除测试文件——这会违背初衷。
项目类型模板
除了基础的伴随测试规则外,agile-tdd 还在 templates/project-types/<type>/ 下提供项目类型模板。每个模板都会启用特定于项目的证据检查,Stop 钩子会在检查伴随测试的基础上执行这些检查。会话审计脚本会将基础检查与每个启用类型的片段组合起来——每种类型的模式相互独立,因此你可以让 TDD 以 warn 模式运行,同时让更严格的类型以 block 模式运行。
可用类型
| 类型 | 检测内容 | 强制要求(除伴随测试外) |
|---|---|---|
tauri | src-tauri/Cargo.toml(单仓库或单体仓库) | cargo check 结果为最新 + bun run typecheck 结果为最新 + 每个受影响应用在最后一次编辑后至少执行 1 次 mcp__tauri__webview_screenshot |
pwa | (计划中)manifest.webmanifest + service worker | 重新构建 service worker + 离线冒烟测试 |
mobile | (计划中)app.json(Expo)/ Podfile / android/build.gradle | 平台构建通过 + 模拟器截图 |
desktop | (计划中)electron/forge 配置 | electron-builder 验证 + 窗口截图 |
启用的类型列在 .tdd-guardrails.yml → project_types 中。安装时,会针对仓库运行每个 templates/project-types/<type>/detect.sh;检测成功的类型会连同其 guardrails.partial.yml 配置块一起追加到配置文件中。
类型的组成
一个类型是一个包含以下内容的文件夹:
detect.sh— 当该类型适用于仓库时,退出码为 0。guardrails.partial.yml— 追加到.tdd-guardrails.yml的配置块。agents-block.partial.md— 在标记之间追加到CLAUDE.md/AGENTS.md的章节。audit.partial.sh— 由tdd-session-audit.sh加载。导出check_<type>_evidence "$ROOT",返回文本格式的违规信息。设置<TYPE>_MODE(大写),供框架决定采用阻止还是警告模式。hooks/*.sh.tmpl— 该类型注册的可选额外钩子(例如 PostToolUse 证据记录器)。README.md— 对该类型的说明文档。
框架会调用 templates/lib/audit-helpers.sh 中的辅助函数来解析 yml、匹配 glob、查找应用根目录以及检查时效性。添加新类型无需修改框架脚本。
安装类型
基础 agile-tdd 安装已遵循上述“手动安装”步骤。对于每个检测到的类型:
- 将
templates/project-types/<type>/guardrails.partial.yml追加到.tdd-guardrails.yml(如果配置块已存在,则进行合并)。 - 在标记对之间将
agents-block.partial.md追加到CLAUDE.md/AGENTS.md。 - 将
hooks/*.sh.tmpl复制到.claude/hooks/、.codex/hooks/和.opencode/hooks/,去掉.tmpl后缀并执行chmod +x。 - 将该类型的匹配器添加到每个 harness 配置中:
- Claude Code(
.claude/settings.json→PostToolUse):为该类型的 PostToolUse 钩子添加匹配器条目。对于tauri:mcp__tauri__webview_screenshot|mcp__tauri__webview_execute_js|mcp__tauri__webview_dom_snapshot|mcp__tauri__manage_window调用$CLAUDE_PROJECT_DIR/.claude/hooks/tdd-record-mcp.sh。 - Codex(
.codex/hooks.json):使用相同的匹配器模式;命令使用bash "$(git rev-parse --show-toplevel)/.codex/hooks/tdd-record-mcp.sh"。 - OpenCode:扩展
.opencode/plugins/tdd-guardrails.js,使其订阅tool.execute.after,并按工具名称筛选,通过node:child_process.spawn启动同一个 shell 脚本。
- Claude Code(
- 将类型标识(例如
tauri)追加到.tdd-guardrails.yml中的project_types。会话审计会在运行时读取此列表。
Tauri MCP 验证(项目类型)
汇总自真实的 Tauri 调试/测试会话的经验。在已检测为 Tauri 的仓库中修改 src-tauri/src/** 或任何 src/{routes,components,hooks}/** 之前,请先阅读本文档。
工具箱(规范参考)
mcp__tauri__driver_session(start)— 始终先调用;后续的 webview 工具都假设会话处于活动状态。mcp__tauri__webview_screenshot— 规范的“我已打开屏幕”信号。传入windowId="main"(Tauri 应用通常有main和tray-panel)。mcp__tauri__webview_execute_js— 对于耗时超过 JS 执行器超时 (约几秒)的调用,通过window.__TAURI_INTERNALS__.invoke(cmd, args).then(r => window.__last = r)以即发即忘方式执行; 改为轮询 DB 或截屏,而不是使用await等待。mcp__tauri__webview_interact/webview_find_element/webview_dom_snapshot中的引用 — 这些依赖window.__MCP__.resolveRef,该函数在开发服务器 HMR 重载后会变为 未定义。优先通过webview_execute_js使用document.querySelector(...).click()。
重新构建流程
- Rust 更改 →
touch src-tauri/src/<file.rs>,强制tauri-dev重新 构建(cargo 的 mtime 监视器)。 - 重新运行 MCP 调用前,监控开发进程输出,直到出现
Finished和MCP Bridge plugin initialized;HMR 只覆盖前端。 - 在 Claude Code 中,优先使用
Monitor,并设置过滤器tail -f tauri.log | grep --line-buffered -E "Finished|error\\[|MCP Bridge plugin initialized"。
验证模式
- 直接读取 DB — 用于状态断言时比
invoke()更省资源:sqlite3 <workspace>/<app>.db "SELECT ..."。 - GPU 卸载检查 —
ps -p $(pgrep -x <app-name>) -o pcpu,etime。 使用 Metal/CUDA 的应用在 GPU 执行工作时 CPU 占用率较低(5–15%);仅使用 CPU 的回退模式则为 200–400%。 - 视觉检查 — 通过
webview_execute_js执行location.assign('/route/...'),等待约 500 ms,然后调用webview_screenshot。
已知注意事项(跨项目模式)
每个项目都有自己的代码库内修复项列表(例如,遵循 LLM
wiki 模式的项目会将其放在
wiki/technical/tauri-gotchas.md 中)。以下内容描述的是模式,实际
文件路径因项目而异。
-
whisper-rs 0.14.x 的
set_abort_callback_safe类型混淆 — 在 v0.14.4 中,trampoline 使用原始闭包 类型实例化,而user_data实际写入的是Box<dyn FnMut() -> bool>。回调解引用了错误的 内存布局并返回无意义的布尔值,导致 whisper 在 0–5% 处以错误-6中止。解决方法:使用unsafe变体set_abort_callback+set_abort_callback_user_data,并手写一个与存储类型匹配的 trampoline:unsafe extern "C" fn abort_trampoline(ud: *mut std::ffi::c_void) -> bool { let f = &mut *(ud as *mut Box<dyn FnMut() -> bool>); f() } let closure: Box<dyn FnMut() -> bool> = Box::new({ let cancel = cancel.clone(); move || cancel.load(Ordering::Relaxed) }); let ud = Box::into_raw(Box::new(closure)) as *mut std::ffi::c_void; unsafe { params.set_abort_callback(Some(abort_trampoline)); params.set_abort_callback_user_data(ud); } -
二进制被终止后,后台任务卡在
running状态 — 一个 tokio 任务 若在执行过程中途退出(cargo 重启、应用崩溃),永远不会将其 DB 行更新为终态。在打开连接池时添加一次协调检查:// db::open_pool, after schema migration sqlx::query( "UPDATE jobs SET status='cancelled', error_message=COALESCE(error_message,'interrupted by app restart'), finished_at=? WHERE status IN ('running','pending')" ).bind(now_iso()).execute(&pool).await?; -
将
open与数据状态耦合的模态框库(例如 Base UI Dialog、某些 Radix 模式)— 当数据 prop 在同一次渲染中变为null, 且open切换为 false 时,模态框会在关闭动画结束前卸载;document.body上的指针事件会一直被拦截, 导致页面无法点击。将open(布尔值)与数据解耦,然后用setTimeout(..., 200)延迟清除数据(或者在库提供onCloseComplete回调时使用该回调)。 -
CREATE TABLE IF NOT EXISTS对已有表不起作用 — 复用的工作区 / DB 不会获取架构文件中新增的列。症状:升级后运行时提示no such column。修复选项:针对每项架构偏差,显式执行ALTER TABLE … ADD COLUMN IF NOT EXISTS;或者,如果 DB 中没有生产数据,则删除并重新初始化。 -
hound::WavReader只能解码 WAV — 对于.mp3/.mp4/.m4a/.webm,先通过 ffmpeg 转为f32le @ 16 kHz mono,再 传给 Whisper:// ffmpeg -hide_banner -loglevel error -nostdin -i <input> // -ac 1 -ar 16000 -f f32le - let mut child = Command::new(ffmpeg) .args(["-hide_banner","-loglevel","error","-nostdin","-i"]) .arg(input) .args(["-ac","1","-ar","16000","-f","f32le","-"]) .stdout(Stdio::piped()).spawn()?; // read stdout, reinterpret bytes as &[f32]
Definition of Done(Tauri)
对于每项涉及每个受影响应用中 affected_paths 的更改(单体仓库:按应用分别处理):
cargo check --manifest-path <app>/src-tauri/Cargo.toml --lib检查通过。bun run typecheck(或tsc --noEmit)检查通过。- 在
<app>/src-tauri/src/**中最后一次touch后,tauri-dev显示Finished。 - 存在配套测试(适用时遵循基本 TDD 规则)。
- 在
<app>/{src-tauri,src}/**下最后一次编辑后,至少调用 1 次mcp__tauri__webview_screenshot。 - 确认操作后的状态:通过数据库查询、DOM 快照或截图中可见的证据进行确认。
tdd-session-audit.sh Stop hook 通过 tauri 模板自动检查 (1)、(2) 和 (5)。第 (3)、(4) 和 (6) 步由 Agent 负责。
与工作流的关系
flowchart LR
A["/agile-story"] --> B[TDD cycle]
B --> C[Red: failing test]
C --> D[Green: minimum code]
D --> E[Refactor]
E --> F{More?}
F -->|Yes| C
F -->|No| G["/agile-refinement"]
此技能在执行期间发挥作用。它与 /agile-story(定义要构建的内容)配合,并为 /agile-refinement(验证结果)提供输入。安装可选强制机制后,该规则也会在每次调用 Write/Edit/MultiEdit 工具时自动应用。